开放的编程资料库

当前位置:我爱分享网 > C#教程 > 正文

C# 使用 AngleSharp 解析 HTML

C#AngleSharp教程展示了如何使用AngleSharp库在C#中解析HTML。

该库还可以解析SVG、MathML或XML。

文档对象模型(DOM)是一种标准的树结构,其中每个节点都包含来自XML结构的组件之一。元素节点和文本节点是两种最常见的节点类型。使用DOM函数,我们可以创建节点、删除节点、更改它们的内容以及遍历节点层次结构。

节点、元素和标签是同义词。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Words</title>
</head>
<body>

<ul>
    <li>sky</li>
    <li>cup</li>
    <li>water</li>
    <li>cloud</li>
    <li>bear</li>
    <li>wolf</li>
</ul>

</body>
</html>

在几个例子中,我们使用这个HTML文件。

C#AngleSharp解析HTML字符串

在第一个示例中,我们从字符串中读取HTML文档。

using AngleSharp;

var html = @"
<html>
<head>
<title>My Title</title>
</head>
<body>
<h1>Heading I</h1>
<p>Paragraph I</p>
<p>Paragraph II</p>
</body>
</html>";

var config = Configuration.Default;
using var context = BrowsingContext.New(config);
using var doc = await context.OpenAsync(req => req.Content(html));

Console.WriteLine(doc.Title);
Console.WriteLine(doc.Body.InnerHtml.Trim());
Console.WriteLine(doc.FirstChild.NodeName.ToLower());
Console.WriteLine(doc.LastChild.NodeName.ToLower());

我们打印文档的标题、正文以及孩子的名字和姓氏。

var config = Configuration.Default;
using var context = BrowsingContext.New(config);

为了设置AngleSharp,我们定义了一个BrowsingContext,我们将Configuration传递给它。

using var doc = await context.OpenAsync(req => req.Content(html));

文档使用OpenAsync加载。

Console.WriteLine(doc.Title);

通过Title属性,我们可以得到文档的标题。

Console.WriteLine(doc.Body.InnerHtml.Trim());

通过Body属性,我们得到文档主体的内部HTML。

Console.WriteLine(doc.FirstChild.NodeName.ToLower());
Console.WriteLine(doc.LastChild.NodeName.ToLower());

我们获取文档的第一个和最后一个子项的名称。

$ dotnet run
My Title
<h1>Heading I</h1>
<p>Paragraph I</p>
<p>Paragraph II</p>
html
html

C#AngleSharpQuerySelectorAll

QuerySelectorAll方法返回文档中与指定选择器组匹配的元素列表。

using AngleSharp;
using AngleSharp.Dom;

var html = @"
<html>
<p>words</p>
<ul>
<li>sky</li>
<li>cup</li>
<li>rock</li>
<li>water</li>
</ul>
</html>";

using var context = BrowsingContext.New(Configuration.Default);
using var doc = await context.OpenAsync(req => req.Content(html));
var els = doc.QuerySelectorAll("li");

foreach (var e in els)
{
    Console.WriteLine(e.Text());
}

在示例中,我们获取了所有的li标签。使用Text方法,我们获取节点的内容文本。

$ dotnet run
sky
cup
rock
water

C#AngleSharp解析HTML文件

在下面的示例中,我们从HTML文件加载文档。

using AngleSharp;

var html = File.ReadAllText(@"/home/janbodnar/Documents/words.html");

var config = Configuration.Default;
using var context = BrowsingContext.New(config);
using var doc = await context.OpenAsync(req => req.Content(html));

var lis = doc.QuerySelectorAll("li");

foreach (var li in lis)
{
    Console.WriteLine(li.InnerHtml);
}

我们使用File.ReadAllText将HTML文件读入一个字符串。然后我们选择所有li标签并打印它们的内部HTML。(在这种情况下,它等同于Text方法。)

C#AngleSharp修改文档

在下面的示例中,我们加载一个HTML文件并对其进行修改。修改后的文档写入磁盘。

using AngleSharp;
using AngleSharp.Text;

var html = File.ReadAllText(@"/home/janbodnar/words.html");

var config = Configuration.Default;
using var context = BrowsingContext.New(config);
using var doc = await context.OpenAsync(req => req.Content(html));

var wli = doc.CreateElement("li");
wli.TextContent = "smile";

var ul = doc.QuerySelector("ul");
ul.FirstElementChild.Remove();
ul.AppendChild(wli);

var p = doc.CreateElement("p");
p.TextContent = $"New paragraph{Symbols.NoBreakSpace}";
doc.Body.AppendChild(p);

File.WriteAllText("/home/janbodnar/words2.html", doc.ToHtml());

在示例中,我们添加了两个元素并删除了一个元素。

var wli = doc.CreateElement("li");
wli.TextContent = "smile";

使用CreateElement创建一个新元素。我们使用TextContent属性设置其内容。

var ul = doc.QuerySelector("ul");
ul.FirstElementChild.Remove();
ul.AppendChild(wli);

我们找到ul元素并使用Remove删除它的第一个子元素。然后我们使用AppendChild附加新创建的元素。

var p = doc.CreateElement("p");
p.TextContent = $"New paragraph{Symbols.NoBreakSpace}";
doc.Body.AppendChild(p);

我们还在正文末尾添加了一段。

File.WriteAllText("/home/janbodnar/words2.html", doc.ToHtml());

修改后的文档使用WriteAllText保存到磁盘。

C#AngleSharp解析HTML页面

在下一个例子中,我们从一个简单的网站加载一个HTML页面。

using AngleSharp;
using AngleSharp.Dom;

var config = Configuration.Default.WithDefaultLoader();
using var context = BrowsingContext.New(config);

var url = "http://webcode.me";

using var doc = await context.OpenAsync(url);
// var title = doc.QuerySelector("title").InnerHtml;
var title = doc.Title;

Console.WriteLine(title);

var pars = doc.QuerySelectorAll("p");

foreach (var par in pars)
{
    Console.WriteLine(par.Text().Trim());
}

从页面的HTML文档中,我们得到它的标题和两段的内容。

var config = Configuration.Default.WithDefaultLoader();

为了能够从HTML页面读取,我们调用了WithDefaultLoader方法。

$ dotnet run
My html page
Today is a beautiful day. We go swimming and fishing.
Hello there. How are you?

HTML页面的C#异步解析

在下一个示例中,我们异步解析多个HTML页面。

using AngleSharp;
using AngleSharp.Dom;

var urls = new[] {
    "http://webcode.me", "http://example.com",
    "http://httpbin.org", "https://google.com", 
    "https://www.rust-lang.org/", "https://golang.org/",
    "https://fsharp.org/", "https://clojure.org/",
    "https://www.perl.org/", "https://gnu.org"
};

var config = Configuration.Default.WithDefaultLoader();
using var context = BrowsingContext.New(config);

var docs = new List<Task<IDocument>>();

foreach (var url in urls)
{
    docs.Add(context.OpenAsync(url));
}

Task.WaitAll(docs.ToArray());

foreach (var t in docs)
{
    var res = t.Result;
    Console.WriteLine(res.Title);

    res.Dispose();
}

该示例异步加载多个网页并解析它们的标题。

$ dotnet run
My html page
Example Domain
httpbin.org
Google
Rust Programming Language
The Go Programming Language
F# Software Foundation
Clojure
The Perl Programming Language - www.perl.org
The GNU Operating System and the Free Software Movement

C#AngleSharp搜索结果

在下一个示例中,我们向Google搜索引擎提交请求并处理结果。

using System.Text.RegularExpressions;
using AngleSharp;
using AngleSharp.Dom;
using AngleSharp.Html.Dom;

using var context = BrowsingContext.New(Configuration.Default.WithDefaultLoader());
using var doc = await context.OpenAsync("https://www.google.com/");
var form = doc.QuerySelector<IHtmlFormElement>("form[action='/search']");

var term = "F# language";

using var res = await form.SubmitAsync(new {q = term});
var links = res.QuerySelectorAll<IHtmlAnchorElement>("a");

foreach (var link in links)
{
    var val = link.Attributes["href"].Value;
    
    if (!val.Contains("google"))
    {
        var rx = new Regex(@"(/url\?q=)([^&]*)(\&)", RegexOptions.Compiled);
        var match = rx.Match(val);

        if (match.Success)
        {
            Console.WriteLine(match.Groups[2]);
        }
    }
}

该示例打印搜索引擎针对给定搜索词返回的所有链接。

var form = doc.QuerySelector<IHtmlFormElement>("form[action='/search']"); 

我们找到表格。

using var res = await form.SubmitAsync(new {q = term});

表单使用SubmitAsync提交。

var links = res.QuerySelectorAll<IHtmlAnchorElement>("a");

从结果中,我们得到了所有链接。

foreach (var link in links)
{
    var val = link.Attributes["href"].Value;
...

我们遍历链接并获取其href属性的内容,其中包含链接。

if (!val.Contains("google"))

我们要排除搜索引擎链接,例如指向条款、隐私和相似性的链接。

var rx = new Regex(@"(/url\?q=)([^&]*)(\&)", RegexOptions.Compiled);

if (match.Success)
{
    Console.WriteLine(match.Groups[2]);
}

我们使用正则表达式来处理链接。我们感兴趣的链接以/url?q=前缀开头。搜索引擎在&后缀后附加一些参数到链接。我们将正则表达式分为三组并选择第二组。

$ dotnet run
https://fsharp.org/
https://fsharp.org/learn/
https://fsharp.org/specs/language-spec/
https://fsharp.org/about/
https://fsharp.org/use/windows/
https://docs.microsoft.com/en-us/dotnet/fsharp/what-is-fsharp
https://medium.com/skills-matter/what-is-the-most-underrated-programming-language-fa...
https://www.planetgeek.ch/2020/12/16/c-vs-f/
https://en.wikipedia.org/wiki/F_Sharp_(programming_language)
https://en.wikipedia.org/wiki/F_Sharp_(programming_language)
https://sk.wikipedia.org/wiki/F_Sharp
...

在本文中,我们使用AngleSharp在C#中解析了HTML文档。

列出所有C#教程。

未经允许不得转载:我爱分享网 » C# 使用 AngleSharp 解析 HTML

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏