Wie man Stackoverflow Exception in HtmlAgilityPack für sehr schlechtes HTML verhindert

c# html-agility-pack stack-overflow

Frage

Ich verwende HtmlAgilityPack in einer MVC 5 Web API. 99,99% der Zeit gibt es keine Probleme ... Seiten laden und ich parse sie, um den Text zu extrahieren, den ich will. Meine API konnte mehrere hundert Mal am Tag ohne Probleme erreicht werden. Es hat glücklich über 2 Millionen Treffer in 24 Stunden in der Vergangenheit behandelt ...

Gelegentlich verursachen jedoch schrecklich gestaltete Websites eine Fehlerreaktion von 500. Dann erhalten alle nachfolgenden Anfragen 500 Fehler und die Site wird vollständig unbrauchbar. Die einzige Lösung in diesem Szenario besteht darin, die Webanwendung neu zu starten. Die Website wird auf Windows Azure gehostet. Ich habe Last-ausgeglichene große Fälle verwendet und einmal CPU-Spitzen bleibt es hoch. In der Vergangenheit lief dies auf einer einzelnen Medium Azure-Instanz (2-Core / 3,5 GB RAM) problemlos.

Der Fehler ist ein Stackoverflow ... den ich nicht verstehen kann.

Beachten Sie, dass dieser Code keine Konsolenanwendung zum Absturz bringt

HtmlWeb web = new HtmlWeb();
HtmlDocument doc = web.Load("http://nursingandmidwiferycareersni.com/");            
Console.Write(doc.DocumentNode.InnerText);

... aber es wird definitiv eine MVC Web App zum Absturz bringen.

In einer einfachen MVC-Webanwendung kann ich jedoch den Stackoverflow-Fehler mit einer Site wie http://nursingandmidwiferycareersni.com/ reproduzieren. Wenn Sie http://nursingandmidwiferycareersni.com/ auf https://validator.w3.org setzen , schaffen Sie einen internen Serverfehler auf validator.w3.org!

Ich werde einen Hack zum HAP-Quellcode machen, wenn es nötig ist, um das zu umgehen ... Momentan benutze ich nur das Nuget-Paket.

Ist es möglich, den Stackoverflow in HAP zu verhindern?
Oder gibt es eine Möglichkeit, nach schrecklichem HTML zu suchen und den Absturz von vornherein zu verhindern?

Beliebte Antwort

Geben Sie etwas wie ParseHtml , wobei die ParseHtml Methode und der ParsedHtml Typ nur Platzhalter sind, die Sie ausfüllen können:

public async Task<ParsedHtml> TryParseHtml(
    string untrustedHtml,
    CancellationToken cancellationToken)
{
    var tcs = new TaskCompletionSource<ParsedHtml>();

    var thread = new Thread(() =>
    {
        ParsedHtml result = ParseHtml(untrustedHtml);
        tcs.TrySetResult(result);
    });
    thread.Start();

    using (cancellationToken.Register(() => tcs.TrySetCanceled()))
    {
        try
        {
            return await tcs.Task;
        }
        catch (OperationCanceledException)
        {
            thread.Abort();
            throw;
        }
    }
}

Die Idee könnte erweitert werden, um effizienter zu sein, indem Threads in dem erfolgreichen Fall wiederverwendet werden, anstatt einen Thread für jede HTML-Seite hochzufeuern und abzureißen.



Related

Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow