使用 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

HtmlAgilityPack HTML操作类库的使用

html解析组件htmlagilitypack如何解析指定的网页

HtmlAgilityPack XPath 错误

在 HtmlAgilityPack 中运行脚本

HTML 解析类库HtmlAgilityPack