httpclient请求超时或返回空内容,主因是未显式设置timeout导致无限等待,以及缺失user-agent等必要请求头引发403或空白响应。

HttpClient 发起请求时,为什么总是超时或返回空内容?
多数情况不是代码写错了,而是没处理好默认行为:HttpClient 默认没有设置超时,DNS 解析慢、服务器响应卡顿就会无限等;另外,很多网站会检查 User-Agent,空头信息直接 403 或返回空白页。
实操建议:
- 始终显式设置
Timeout,比如new HttpClient() { Timeout = TimeSpan.FromSeconds(10) } - 务必添加合法的请求头,至少包含
User-Agent,例如:client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") - 如果目标站启用了 gzip 压缩,HttpClient 默认能自动解压,但某些老旧服务可能返回异常编码,此时可加
Accept-Encoding: gzip, deflate并确保AutomaticDecompression已启用(需用WebClient或自定义HttpClientHandler)
用正则提取 HTML 内容,哪些地方最容易出错?
正则不是不能用,但 HTML 是嵌套结构,而正则不擅长处理嵌套。常见翻车点是标签跨行、属性顺序不定、存在注释或 JS 脚本干扰——比如想匹配 <title>.*?</title>,但实际 HTML 是 <title>\n 网站名\n</title>,. 默认不匹配换行符,结果就为空。
实操建议:
- 用
RegexOptions.Singleline让.匹配换行符,例如:new Regex(@"<title>(.*?)</title>", RegexOptions.Singleline) - 避免写过于宽泛的模式,如
<div.>(.*?)</div.>—— 它会贪婪匹配到**最后一个**,中间可能嵌套了几十层 div - 优先提取有明确标识的内容:id、class 名固定,或前后有稳定锚点文本(比如“发布时间:”后面跟日期)
- 真正需要解析结构时,别硬扛正则,改用
HAP(HtmlAgilityPack),它专为 HTML 设计,容忍 malformed 标签,API 直观,NuGet 包名就是HtmlAgilityPack
HttpClient 和 HtmlAgilityPack 配合抓取,怎么避免中文乱码?
典型现象是返回的字符串里中文全变成问号或方块,根本原因是响应流的编码没被正确识别。HttpClient 的 GetStringAsync() 会尝试从响应头 Content-Type 中读取 charset,但很多网站根本不设或设错(比如声明 utf-8 却实际发 GB2312)。
实操建议:
- 不用
GetStringAsync(),改用GetByteArrayAsync()获取原始字节,再手动按目标编码解码:Encoding.GetEncoding("GB2312").GetString(bytes) - 先用浏览器开发者工具看 Network → Response Headers →
Content-Type,再查网页源码<meta charset="...">或<meta http-equiv="Content-Type">,两者不一致时以 meta 为准 - 如果编码不确定,可用
Ude.CSharp(NuGet 包)做自动探测,但注意它有性能开销,别在高频爬取中每页都调用
爬虫跑几次就 IP 被封?怎么简单降低被识别风险?
不是所有网站都有反爬,但一旦出现 403、503、或返回验证码页面,基本说明请求特征太像机器人。HttpClient 本身无指纹,问题出在使用方式上。
实操建议:
- 加随机延时:别用
Thread.Sleep(1000)这种固定值,改用await Task.Delay(new Random().Next(800, 2000)) - 每次请求换
User-Agent:维护一个列表,每次随机取一个,避免所有请求头完全一致 - 不要并发猛刷:单 IP 每秒超过 2–3 次请求,多数中小站点的 WAF 就会标记异常;如需提速,优先考虑分布式 IP 或代理池,而不是本地开 20 个 HttpClient 实例
- 留意 robots.txt:虽然不强制,但
https://example.com/robots.txt里禁止的路径,真去扫大概率触发风控规则
真正麻烦的从来不是怎么取到数据,而是怎么让服务器相信你是个普通用户——头信息、节奏、Cookie 复用、JS 渲染依赖,这些才是分水岭。正则和 HttpClient 只是工具,用得越“生硬”,越容易被拦在门外。











