使用 HtmlAgilityPack 下载网页时违反 HTTP 协议
Posted
技术标签:
【中文标题】使用 HtmlAgilityPack 下载网页时违反 HTTP 协议【英文标题】:HTTP Protocol violation when downloading webpage using HtmlAgilityPack 【发布时间】:2011-01-11 10:41:10 【问题描述】:我正在尝试解析来自 www.mediafire.com 的下载页面,但是当我尝试将页面加载到 htmlDocument
时,我确实经常收到带有以下消息的 System.Net.WebException
:
服务器提交了一个协议 违反。 Section=ResponseStatusLine
这是我的代码:
HtmlAgilityPack.HtmlWeb web = new HtmlAgilityPack.HtmlWeb();
HtmlAgilityPack.HtmlDocument doc = null;
string url = www.mediafire.com/?abcdefghijkl //There are many different links
try
doc = web.Load(url); //From 30 links, usually only 10 load properly
catch (WebException)
任何想法为什么只有 30 个链接中的 10 个有效(链接每次都会更改,因为我的程序是“搜索引擎”)以及我如何解决问题?
当我在浏览器中加载这些网站时,一切正常。
我尝试将以下几行添加到我的 app.config 中,但这也无济于事
<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing="true" />
</settings>
</system.net>
【问题讨论】:
他们可能使用用户代理/cookie/header 嗅探来检测非网络浏览器。您可以尝试使用WebRequest
并构造一个类似于您的浏览器的请求。
您能否提供更多有关这样做的信息?也许是教程的链接或其他内容?
【参考方案1】:
这与 Html Agility Pack 没有直接关系,而是与底层 HTTP/socket 层相关。此错误表示服务器未发回正确的 HTTP 状态行。
状态行在此处的 HTTP RFC 中定义:http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html
我引用:
响应消息的第一行 是状态行,由 协议版本后跟数字 状态码及其相关的文本 短语,每个元素由 SP 字符。不允许使用 CR 或 LF 最终的 CRLF 序列除外。
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
您可以添加带有完整十六进制报告的套接字跟踪来检查:
<configuration>
<system.diagnostics>
<sources>
<source name="System.Net.Sockets" tracemode="includehex">
<listeners>
<add name="System.Net.Sockets" type="System.Diagnostics.TextWriterTraceListener" initializeData="SocketTrace.log" />
</listeners>
</source>
</sources>
<switches>
<add name="System.Net.Sockets" value="Verbose"/>
</switches>
<trace autoflush="true" />
</system.diagnostics>
</configuration>
这将在当前执行目录中创建一个 SocketTrace.log 文件。看看那里,协议违规应该是可见的。如果它不是太大,你可以在这里发布:-)
不幸的是,如果您不拥有服务器,则无能为力(如果您已经添加了 useUnsafeHeaderParsing 设置,这很好)但在这些情况下会正常失败。
【讨论】:
您唯一能做的就是联系服务器负责人并告知他们问题所在。取决于他们,他们可能会决定解决问题,但就像西蒙说你无法控制服务器,他们不必修复它【参考方案2】:将 keep alive 属性设置为 false 将解决此问题。但我不确定 htmlagilitypack 是否有这个属性。所以使用 WebClient 会是更好的选择。
这对我有用。 不要直接使用 web.Load 加载 url,而是使用您的自定义 WebClient 下载所需 url 的 html。在您的自定义 WebClient 中覆盖 GetWebRequest 方法以使 HttpWebRequest.KeepAlive = false。现在在 web.Load() 中加载下载的文件。
MyWebClient client = new MyWebClient();
client.DownloadFile(searchURL, @"C:\\index.html");
var doc = web.Load("C:\\index.html");
覆盖 GetWebRequest
using System;
using System.Net;
namespace MyProject
internal class CustomWebClient : WebClient
protected override WebRequest GetWebRequest(Uri address)
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest)
(request as HttpWebRequest).KeepAlive = false;
return request;
【讨论】:
您是在暗示他正在使用的服务器在处理 KeepAlive 请求时遇到问题,还是直接使用 WebClient 可以避免该问题?你从来没有真正说出你认为他的问题是什么。 是的,问题出在服务器的响应中。将 keep alive 设置为 false 将解决此问题。但我不确定 htmlagilitypack 是否具有 keep alive 属性。所以使用 WebClient 将是一个更好的选择。谢谢!以上是关于使用 HtmlAgilityPack 下载网页时违反 HTTP 协议的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET 网络爬虫小研究 HtmlAgilityPack