Нарушение протокола HTTP при загрузке веб-страницы с использованием HtmlAgilityPack - PullRequest
2 голосов
/ 11 января 2011

Я пытаюсь проанализировать страницы загрузки с www.mediafire.com, но я действительно часто получаю System.Net.WebException со следующим сообщением, когда пытаюсь загрузить страницу в HtmlDocument:

Сервер совершил нарушение протокола.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)
{

}

Любые идеи, почему работают только 10 из 30 ссылок (ссылки меняются каждый раз, потому что моя программа является «поисковой системой»)) и как я могу решить эту проблему?

Когда я загружаю эти сайты в браузере, все работает нормально.


Я попытался добавить следующие строки в свое приложение.конфиг, но это тоже не помогает

<system.net>
    <settings>
        <httpWebRequest useUnsafeHeaderParsing="true" />
    </settings>
</system.net>

Ответы [ 2 ]

3 голосов
/ 11 января 2011

Это не связано напрямую с 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, что хорошо), но в этих случаях происходит изящная ошибка.

0 голосов
/ 11 июня 2016

Установка свойства keep alive на false исправит эту проблему.Но я не уверен, что htmlagilitypack обладает этим свойством.Поэтому использование WebClient было бы лучшей альтернативой.

Это сработало для меня.Вместо прямой загрузки URL-адреса с помощью web.Load загрузите HTML-код нужного URL-адреса, используя свой пользовательский WebClient.В вашем пользовательском методе 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;
        }
    }
}
...