AngleSharp 是一个功能强大的 .NET 库,用于解析 HTML、XML 和 CSS。它提供了一个直观的 API,使得在 C# 中处理 Web 文档变得简单高效。本文将详细介绍 AngleSharp 的使用方法,并提供多个实用的例子。
1. 安装
首先,通过 NuGet 包管理器安装 AngleSharp:
Install-Package AngleSharp

2. 基本用法
2.1 解析 HTML 文档
using AngleSharp;using AngleSharp.Dom;using System;
class Program{    static async Task Main(string[] args)    {        // 配置 AngleSharp        var config = Configuration.Default;         // 创建一个新的上下文        var context = BrowsingContext.New(config);
        // 解析 HTML 字符串        var html = "<html><body><h1>Hello, AngleSharp!</h1></body></html>";        var document = await context.OpenAsync(req => req.Content(html));
        // 获取并打印 h1 元素的文本        var h1 = document.QuerySelector("h1");        Console.WriteLine(h1.TextContent); // 输出: Hello, AngleSharp!    }}

2.2 从 URL 加载文档
static async Task Main(string[] args){    var config = Configuration.Default.WithDefaultLoader();    var context = BrowsingContext.New(config);
    var document = await context.OpenAsync("https://www.163.com");
    var title = document.QuerySelector("title");    Console.WriteLine($"Page title: {title.TextContent}");}
3. 高级用法
3.1 选择元素
AngleSharp 支持多种选择元素的方法:
static async Task Main(string[] args){    var config = Configuration.Default.WithDefaultLoader();    var context = BrowsingContext.New(config);
    var document = await context.OpenAsync("https://www.cnblogs.com/");
    // 通过 ID 选择    var elementById = document.GetElementById("myId");
    // 通过类名选择    var elementsByClass = document.GetElementsByClassName("post-item-title");    foreach (var element in elementsByClass)    {        Console.WriteLine(element.TextContent);    }
    // 通过标签名选择    var elementsByTag = document.GetElementsByTagName("div");
    // 使用 CSS 选择器    var elementBySelector = document.QuerySelectorAll(".post-item-text > p");    foreach (var element in elementBySelector)    {        Console.WriteLine(element.TextContent);    }
    var elementsBySelector = document.QuerySelectorAll("div.myClass");
    foreach (var element in elementsBySelector)    {        Console.WriteLine(element.TextContent);    }}
3.2 修改文档
AngleSharp 允许你动态修改文档:
static async Task Main(string[] args){    var config = Configuration.Default.WithDefaultLoader();    var context = BrowsingContext.New(config);
    var document = await context.OpenAsync(req => req.Content("<html><body></body></html>"));
    var body = document.Body;
    // 创建新元素    var newDiv = document.CreateElement("div");    newDiv.ClassName = "newClass";    newDiv.TextContent = "This is a new div";
    // 添加到文档    body.AppendChild(newDiv);
    // 修改现有元素    var existingDiv = document.QuerySelector("div");    existingDiv.SetAttribute("data-custom", "value");
    // 删除元素    var elementToRemove = document.QuerySelector(".removeMe");    elementToRemove?.Remove();
    Console.WriteLine(document.DocumentElement.OuterHtml);}
3.3 处理表单
AngleSharp 可以用来处理 HTML 表单:
static async Task Main(string[] args){    var config = Configuration.Default.WithDefaultLoader();    var context = BrowsingContext.New(config);
    var html = @"    <form id='loginForm'>        <input type='text' name='username' />        <input type='password' name='password' />        <input type='submit' value='Login' />    </form>";
    var document = await context.OpenAsync(req => req.Content(html));
    var form = document.QuerySelector("#loginForm") as IHtmlFormElement;    var usernameInput = form["username"] as IHtmlInputElement;    var passwordInput = form["password"] as IHtmlInputElement;
    usernameInput.Value = "myUsername";    passwordInput.Value = "myPassword";
    // 模拟表单提交    await form.SubmitAsync();}
3.4 使用 CSS 选择器
AngleSharp 支持复杂的 CSS 选择器:
var html = @"<div>    <p>First paragraph</p>    <p>Second paragraph</p>    <p>Third paragraph</p></div>";
var document = await context.OpenAsync(req => req.Content(html));
// 选择第二个段落var secondP = document.QuerySelector("p:nth-child(2)");Console.WriteLine(secondP.TextContent); // 输出: Second paragraph
// 选择带有特定类的段落var highlightedP = document.QuerySelector("p.highlight");Console.WriteLine(highlightedP.TextContent); // 输出: Second paragraph
// 选择所有段落var allParagraphs = document.QuerySelectorAll("p");foreach (var p in allParagraphs){    Console.WriteLine(p.TextContent);}

3.5 解析和操作 CSS
AngleSharp 也可以用来解析和操作 CSS:

static async Task Main(string[] args){    var config = Configuration.Default.WithDefaultLoader();    var context = BrowsingContext.New(config);
    var css = @"    body {        font-family: Arial, sans-serif;        background-color: #f0f0f0;    }    .highlight {        color: red;        font-weight: bold;    }";
    var parser = new CssParser();    var stylesheet = parser.ParseStyleSheet(css);
    foreach (var rule in stylesheet.Rules)    {        if (rule is ICssStyleRule styleRule)        {            Console.WriteLine($"Selector: {styleRule.SelectorText}");            foreach (var declaration in styleRule.Style)            {                Console.WriteLine($"  {declaration.Name}: {declaration.Value}");            }        }    }}

3.6 执行 JavaScript
虽然 AngleSharp 主要用于 HTML 和 CSS 解析,但它也提供了一个基本的 JavaScript 执行环境:
static async Task Main(string[] args)  {    var config = Configuration.Default.WithJs();    var context = BrowsingContext.New(config);
    var document = await context.OpenAsync(req => req.Content("<div id='result'></div>"));
    var script = @"    document.getElementById('result').textContent = 'Hello from JavaScript!';    ";
    var engine = context.GetService<JsScriptingService>();    var jsValue = engine.EvaluateScript(document, script);
    var result = document.GetElementById("result");    Console.WriteLine(result.TextContent); // 输出: Hello from JavaScript!}  

3.7 处理表格数据
AngleSharp 可以很方便地处理 HTML 表格:
static async Task Main(string[] args){    var config = Configuration.Default;    var context = BrowsingContext.New(config);    var html = @"    <table id='dataTable'>        <tr><th>Name</th><th>Age</th></tr>        <tr><td>John</td><td>30</td></tr>        <tr><td>Jane</td><td>25</td></tr>    </table>";
    var document = await context.OpenAsync(req => req.Content(html));
    var table = document.GetElementById("dataTable") as IHtmlTableElement;
    foreach (var row in table.Rows)    {        var cells = row.Cells;        if (cells.Length == 2)        {            Console.WriteLine($"Name: {cells[0].TextContent}, Age: {cells[1].TextContent}");        }    }}  

3.8 解析 XML
AngleSharp 不仅可以解析 HTML,还可以解析 XML:
static async Task Main(string[] args){    var xml = @"    <root>        <element attribute='value'>            <child>Content</child>        </element>    </root>"    ;
    var parser = new XmlParser();    var document = await parser.ParseDocumentAsync(xml);
    var root = document.DocumentElement;    var element = root.FirstElementChild;    var attribute = element.GetAttribute("attribute");    var childContent = element.FirstElementChild.TextContent;
    Console.WriteLine($"Attribute: {attribute}");    Console.WriteLine($"Child content: {childContent}");}  

4. 错误处理和最佳实践
4.1 使用 try-catch 块
始终使用 try-catch 块来处理可能出现的异常:
try{    var document = await context.OpenAsync("https://example.com");    // 处理文档...}catch (AngleSharp.Io.NetworkException ex){    Console.WriteLine($"Network error: {ex.Message}");}catch (Exception ex){    Console.WriteLine($"An unexpected error occurred: {ex.Message}");}
4.2 检查元素是否存在
在访问元素之前,始终检查元素是否存在:
var element = document.QuerySelector(".myClass");if (element != null){    Console.WriteLine(element.TextContent);}else{    Console.WriteLine("Element not found");}
4.3 使用 Linq 与 AngleSharp
AngleSharp 的查询结果可以很好地与 Linq 结合使用:
var paragraphs = document.QuerySelectorAll("p")    .Where(p => p.ClassList.Contains("important"))    .Select(p => p.TextContent);
foreach (var text in paragraphs){    Console.WriteLine(text);}
5. 结论
AngleSharp 是一个强大而灵活的库,它为 C# 开发者提供了丰富的 HTML、CSS 和 XML 处理功能。从简单的文档解析到复杂的 DOM 操作,AngleSharp 都能胜任。
通过本文提供的示例,你应该能够处理大多数与 Web 文档解析和操作相关的任务。AngleSharp 的 API 设计直观,使得即使是复杂的操作也能够简单地实现。
在使用 AngleSharp 时,请记住正确处理异常,并考虑性能影响。对于需要处理大量文档或执行频繁操作的情况,可能需要考虑使用缓存或其他优化技术。
该文章在 2024/10/30 14:56:48 编辑过