Violación del protocolo HTTP al descargar una página web usando HtmlAgilityPack

.net c# html-agility-pack system.net.webexception

Pregunta

Estoy tratando de analizar las páginas de descarga de www.mediafire.com, pero a menudo recibo una System.Net.WebException con el siguiente mensaje, cuando intento cargar una página en un documento HtmlDocument :

El servidor ha ocasionado una violación del protocolo. Sección = ResponseStatusLine

Este es mi código:

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)
{

}

¿Alguna idea de por qué solo 10 de 30 enlaces funcionan (los enlaces cambian cada vez, porque mi programa es un "motor de búsqueda") y cómo puedo resolver el problema?

Cuando carga esos sitios en mi navegador, todo funciona bien.


He intentado agregar las siguientes líneas a mi app.config, pero eso tampoco ayuda

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

Respuesta aceptada

Esto no está relacionado directamente con el paquete de agilidad Html, sino con la capa subyacente de HTTP / socket. Este error significa que el servidor no está devolviendo una línea de estado HTTP correcta.

La línea de estado se define en HTTP RFC disponible aquí: http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html

Yo cito:

La primera línea de un mensaje de respuesta es la línea de estado, que consiste en la versión del protocolo seguida de un código de estado numérico y su frase textual asociada, con cada elemento separado por caracteres SP. No se permite CR o LF, excepto en la secuencia final de CRLF.

   Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

Puede agregar trazas de socket con informe hexadecimal completo para verificar esto:

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

Esto creará un archivo SocketTrace.log en el directorio de ejecución actual. Echa un vistazo allí, la violación del protocolo debe ser visible. Puedes publicarlo aquí si no es demasiado grande :-)

Desafortunadamente, si no es el propietario del servidor, no hay mucho que pueda hacer (si ya agregó la configuración useUnsafeHeaderParsing, lo cual es bueno), pero falle correctamente en estos casos.


Respuesta popular

La configuración de mantener la propiedad viva en falso solucionará este problema. Pero no estoy seguro si htmlagilitypack tiene esta propiedad. Entonces usar WebClient sería una mejor alternativa.

Esto funcionó para mí. En lugar de cargar directamente la url con web.Cargue, descargue el html de la url deseada usando su WebClient personalizado. En su cliente web, sustituya el método GetWebRequest para que HttpWebRequest.KeepAlive = false. Ahora carga el archivo descargado en web.Load ().

MyWebClient client = new MyWebClient();
client.DownloadFile(searchURL, @"C:\\index.html");
var doc = web.Load("C:\\index.html");

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


Related

Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué