使用 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 协议的主要内容,如果未能解决你的问题,请参考以下文章