HttpClient 是现代 C# 爬虫首选,需异步调用、检查状态码、设置 User-Agent;HtmlAgilityPack 解析 HTML 时须处理编码与空节点;静态页用 HttpClient 足够,动态渲染页应选 PuppeteerSharp。
HttpClient 获取网页 HTML 最直接可靠现代 C# 爬虫首选 HttpClient,它支持异步、自动处理重定向和 Cookie(需手动配置),比已过时的 WebClient 更稳定。同步调用(DownloadString)在 .NET 6+ 中已被标记为过时,必须用 GetAsync + ReadAsStringAsync。
常见错误:忽略响应状态码,直接读取内容,导致空字符串或异常;或未设置 User-Agent 被服务器拒绝(返回 403)。
response.IsSuccessStatusCode,否则 404/500 也会进后续解析流程client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
HttpClient 拿到的是原始 HTML,无法获取动态内容——此时不是代码问题,而是技术选型错误var client = new HttpClient();
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
var response = await client.GetAsync("https://example.com");
if (!response.IsSuccessStatusCode)
throw new Exception($"HTTP {response.StatusCode}");
var html = await response.Content.ReadAsStringAsync();HtmlAgilityPack 解析 HTML 结构HtmlAgilityPack 是 C# 生态中事实标准的 HTML 解析库,能容忍 malformed HTML(如缺失闭合标签),比正则匹配安全得多。NuGet 包名就是 HtmlAgilityPack,.NET Core / .NET 5+ 全支持。
容易踩的坑:直接对 html 字符串调用 LoadHtml() 却忽略编码问题,中文乱码;或用 SelectNodes("//div[@class='item']") 但没确认节点是否为 null 就访问 InnerText,引发 NullReferenceException。
doc.LoadHtml(html, Encoding.GetEncoding("gb2312"))
SelectNodes 或 SelectSingleNode 返回值必须判空,再取 InnerText 或 GetAttributeValue
contains(@class, 'xxx') 比 @class='xxx' 更鲁棒vardoc = new HtmlDocument(); doc.LoadHtml(html); var nodes = doc.DocumentNode.SelectNodes("//div[contains(@class, 'title')]"); if (nodes != null) foreach (var node in nodes) Console.WriteLine(node.InnerText.Trim());
多数静态页面只需加 User-Agent 和 Referer;但遇到登录态依赖或基础 JS 检查(如生成时间戳、计算 token),就得维持会话上下文。
关键点:用同一个 HttpClient 实例复用连接和 Cookie 容器,不要每次新建;HttpClientHandler 的 UseCookies = true 必须开启(默认是 true,但显式写上更安心)。
Referer 头要与目标 URL 同域,否则部分站点拒收(例如从 https://a.com 请求 https://b.com/api 会被拦截)Set-Cookie,后续请求自动携带——前提是没换 HttpClient 实例document.cookie = xxx 或 Math.random() 生成参数,不能硬编码,得用 JavaScriptEngineSwitcher 或预编译 JS 片段(小范围可行),否则应转向 PuppeteerSharpPuppeteerSharp?当目标页面大量使用 fetch、Vue/React 渲染、或有滑动验证、鼠标轨迹检测时,HttpClient + HtmlAgilityPack 就失效了。这时候 PuppeteerSharp(Chromium 自动化)是更实际的选择,而非强行逆向加密逻辑。
注意:它体积大(约 80MB Chromium 二进制)、启动慢、内存占用高,不适合高频轻量采集;且需要确保运行环境有可用的 Chromium(或启用 DownloadBrowser = true 自动下载)。
browser.CloseAsync() 或 DisposeAsync(),否则残留进程吃光内存WaitForSelectorAsync("div.content"),别用 Thread.Sleep
真实场景里,90% 的企业内网报表、政府公开数据页,HttpClient 足够;剩下 10% 才需要评估是否值得引入 PuppeteerSharp。