DocumentNode为null主因是传入空字符串、null或编码损坏数据,须先判空再查询;XPath不支持CSS选择器,需用contains()等函数匹配松散HTML;中文乱码因编码未对齐,应按响应头或meta指定解码;JS动态内容需换用PuppeteerSharp。

HtmlAgilityPack.LoadHtml() 后 DocumentNode 为 null 怎么办
这不是 HTML 写错了,而是你传了空字符串、null 或编码损坏的字节流进去,HtmlDocument 解析失败后 DocumentNode 就是 null,后续任何 SelectSingleNode() 都直接抛 NullReferenceException。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 永远在调用
SelectNodes()前加判断:if (doc.DocumentNode == null) return;或抛明确异常 - 用
LoadHtml(htmlString?.Trim()),避免空白字符串触发静默失败 - 从 HTTP 拿到响应后,先检查
response.IsSuccessStatusCode和response.Content.ReadAsStringAsync()是否为空,再喂给LoadHtml() - 解析纯片段(如只有
<div>xxx</div>)时,可手动包裹一层<html><body>...</body></html>,防止节点树构建中断
为什么 SelectNodes("//a[@href]") 找不到链接,但浏览器里明明有
HtmlAgilityPack 不支持 CSS 选择器,只认 XPath 1.0;而真实网页的 class 属性常含空格、大小写混用、引号不统一,或标签嵌套松散,导致严格 XPath 匹配失败。
实操建议:
立即学习“前端免费学习笔记(深入)”;
-
SelectNodes()参数必须是合法 XPath,写"div.content"会静默返回空,得写"//div[contains(@class, 'content')]" - 属性值含单引号?整个 XPath 改用双引号包裹:
"//a[@href=\"https://x.com?q=1&s=2\"]" - 查子节点更稳:用
doc.DocumentNode.Descendants("a")替代SelectNodes("//a"),它不依赖路径深度,也不怕标签大小写 - 调试时输出
doc.DocumentNode.OuterHtml.Substring(0, 500),确认实际解析出的 DOM 结构是否和你预期一致
提取 href 后怎么处理相对路径和协议相对 URL
GetAttributeValue("href", "") 返回的是原始值,可能是 "./page.html"、"//cdn.example.com/style.css" 或 "javascript:void(0)",直接当完整 URL 用会出错。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 过滤掉伪链接:
Where(href => !href.StartsWith("javascript:", StringComparison.OrdinalIgnoreCase) && !href.StartsWith("mailto:", StringComparison.OrdinalIgnoreCase)) - 补全相对路径:用
Uri.TryCreate(new Uri(baseUri), href, out Uri result),其中baseUri是原始页面 URL - 判断是否为合法 URI:
Uri.IsWellFormedUriString(href, UriKind.Absolute),否则跳过或补全 - 别依赖
Uri.IsAbsoluteUri判断——协议相对 URL(如"//example.com")返回false,但它仍是有效地址
HttpClient 拿到的内容乱码,HtmlAgilityPack 解析后中文变问号或空格
根本不是 HtmlAgilityPack 的问题,而是 HttpClient.GetStringAsync() 默认按 UTF-8 解码,但目标页可能声明 charset=gb2312,或响应头与 meta 标签不一致。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 别用
GetStringAsync(),改用GetByteArrayAsync()拿到原始字节,再按响应头Content-Type中的charset指定编码解码 - 若响应头没带 charset,查 HTML 中
<meta charset="gbk">或<meta http-equiv="Content-Type" content="text/html; charset=gb2312"> - 用
HtmlWeb类时,显式设web.OverrideEncoding = Encoding.GetEncoding("gb2312");用LoadHtml()时,确保传入的是已正确解码的string - 注意
HtmlDocument.PreserveWhitespace = true可能导致中文换行被当成多余空白合并,影响文本提取效果
最易被忽略的一点:HtmlAgilityPack 不执行 JavaScript,所有由 JS 动态插入的 DOM 节点(比如单页应用里的内容、懒加载列表)它根本看不到。这时候不是解析逻辑有问题,而是该换 PuppeteerSharp 或 Playwright.NET 了。


















