C# (.NET) 中的 HTML 解析:HtmlAgilityPack 和 AngleSharp 库

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C# (.NET) 中的 HTML 解析:HtmlAgilityPack 和 AngleSharp 库概述



HTML 解析是开发网页抓取工具、内容分析器或自动化测试时的关键任务之一。在 .NET 生态系统中,有几个强大的库允许您从 HTML 文档中提取数据、操作 DOM 树并执行复杂查询。在本文中,我们将介绍两个最流行的库:HtmlAgilityPack 和 AngleSharp。您将了解它们的特点、优势,并获得现成的 C# 代码示例。



HtmlAgilityPack:经典方法



HtmlAgilityPack (HAP) 是 .NET 中最古老且最常用的 HTML 解析库。它提供了一个直观的 API 用于导航 DOM 树,支持 XPath 和 LINQ 查询。主要功能:



  • 从字符串、文件或 URL 加载 HTML。
  • 支持 XPath 1.0 以精确查找元素。
  • 处理属性、文本和嵌套节点。
  • 自动修复格式错误的 HTML(例如,未闭合的标签)。


安装

通过 NuGet 安装库:

Install-Package HtmlAgilityPack

或通过 .NET CLI:

dotnet add package HtmlAgilityPack


示例:提取新闻标题

假设我们需要从新闻网站解析标题。以下是使用 HAP 和 XPath 的方法:



using HtmlAgilityPack;using System;using System.Linq;

class Program{ static void Main() { // 加载 HTML 文档 var web = new HtmlWeb(); var doc = web.Load("https://example-news.com"); // 选择所有 class 为 "news-title" 的 h2 标题 var titles = doc.DocumentNode .SelectNodes("//h2[@class='news-title']"); if (titles != null) { foreach (var title in titles) { Console.WriteLine(title.InnerText.Trim()); } } }}


在此示例中,我们使用 XPath 表达式 //h2[@class='news-title'] 来查找所有具有指定 class 的 <h2> 元素。方法 SelectNodes 返回节点集合,而 InnerText 提取不带 HTML 标签的文本。



处理属性

通常需要获取属性的值,例如 <a> 标签中的链接:



var links = doc.DocumentNode.SelectNodes("//a[@href]");if (links != null){    foreach (var link in links)    {        string href = link.GetAttributeValue("href", "");        Console.WriteLine(href);    }}


AngleSharp:带有 CSS 选择器的现代解析器



AngleSharp 是一个更现代的库,不仅支持 XPath,还支持 CSS 选择器,这使得熟悉 Web 技术的开发人员使用起来更加方便。它还完全符合 W3C 标准,并且可以处理动态内容。



  • 支持 CSS 选择器(类似于 jQuery)。
  • 处理 HTML、XML、SVG 和 MathML。
  • 能够执行 JavaScript(通过扩展)。
  • 异步文档加载。


安装

dotnet add package AngleSharp


示例:使用 CSS 选择器提取数据

重复之前的示例,但现在使用 AngleSharp 和 CSS 选择器:



using AngleSharp;using AngleSharp.Html.Parser;using System;using System.Linq;using System.Threading.Tasks;

class Program{ static async Task Main() { // 创建解析器 var parser = new HtmlParser(); // 加载 HTML(可以从字符串或 URL) var document = await parser.ParseDocumentAsync( a

推荐