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#教程。