使用HtmlAgilityPack下载网页时违反HTTP协议

时间:2011-01-11 10:41:11

标签: c# .net html-agility-pack system.net.webexception

我正在尝试从www.mediafire.com解析下载页面,但是当我尝试将页面加载到System.Net.WebException时,我经常会收到HtmlDocument以及以下消息: / p>

  

服务器提交了协议   违反。节= 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>

2 个答案:

答案 0 :(得分:3)

这与Html Agility Pack没有直接关系,而是与底层HTTP /套接字层有关。此错误表示服务器未发送回正确的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设置,这很好)但在这些情况下优雅地失败。

答案 1 :(得分:0)

将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;
        }
    }
}