Zobacz wygenerowane źródło (po AJAX / JavaScript) w C #

Czy istnieje sposób na wyświetlenie wygenerowanego źródła strony internetowej (kodu po wykonaniu wszystkich operacji wywołania AJAX i JavaScript DOM) z aplikacji C # bez otwierania przeglądarki z kodu?

Wyświetlanie strony początkowej za pomocą aWebRequest lubWebClient obiekt działa poprawnie, ale jeśli strona w znacznym stopniu wykorzystuje JavaScript do zmiany DOM przy ładowaniu strony, nie zapewnia to dokładnego obrazu strony.

Próbowałem użyćSelen iWatin Struktury testowe interfejsu użytkownika i działają doskonale, dostarczając wygenerowane źródło tak, jak wygląda po zakończeniu wszystkich manipulacji JavaScript. Niestety, robią to, otwierając rzeczywistą przeglądarkę internetową, która jest bardzo wolna. Zaimplementowałem serwer selenu, który odciąża tę pracę na inny komputer, ale nadal istnieje znaczne opóźnienie.

Czy istnieje biblioteka .Net, która załaduje i przeanalizuje stronę (np. Przeglądarkę) i wypluje wygenerowany kod? Oczywiście Google i Yahoo nie otwierają przeglądarek dla każdej strony, którą chcą pająk (oczywiście mogą mieć więcej zasobów niż ja ...).

Czy istnieje taka biblioteka lub czy nie mam szczęścia, chyba że chcę rozszyfrować kod źródłowy przeglądarki open source?

ROZWIĄZANIE

Cóż, dziękuję wszystkim za pomoc. Mam rozwiązanie robocze, które jest około 10 razy szybsze niż Selenium. Zabiegać!

Dzięki temustary artykuł z beanoftware Udało mi się użyć kontrolki System.Windows.Forms.WebBrowser, aby pobrać stronę i przeanalizować ją, a następnie podać wygenerowane źródło. Mimo że kontrola jest w systemie Windows.Forms, nadal można ją uruchomić z Asp.Net (co właśnie robię), pamiętaj tylko o dodaniu System.Window.Forms do referencji projektu.

W kodzie są dwie ważne rzeczy. Po pierwsze, formant WebBrowser jest wywoływany w nowym wątku. To dlatego, że musi działać na ajednopasmowe mieszkanie.

Po drugie, zmienna GeneratedSource jest ustawiona w dwóch miejscach. Nie jest to spowodowane inteligentną decyzją projektową :) Nadal pracuję nad tym i zaktualizuję tę odpowiedź, kiedy skończę. wb_DocumentCompleted () jest wywoływany wiele razy. Najpierw po pobraniu początkowego kodu HTML, a następnie po zakończeniu pierwszej rundy JavaScript. Niestety strona, którą ocieram, ma 3 różne etapy ładowania. 1) Załaduj początkowy HTML 2) Wykonaj pierwszą rundę manipulacji JavaScript DOM 3) Zatrzymaj na pół sekundy, a następnie wykonaj drugą rundę manipulacji JS DOM.

Z jakiegoś powodu druga runda nie jest spowodowana przez funkcję wb_DocumentCompleted (), ale zawsze jest łapana, gdy wb.ReadyState == Complete. Dlaczego więc nie usunąć go z wb_DocumentCompleted ()? Nadal nie jestem pewien, dlaczego nie został on tam złapany i właśnie w tym miejscu zalecono umieszczenie go w artykule dotyczącym oprogramowania koralikowego. Będę się tym zajmował. Chciałem po prostu opublikować ten kod, aby każdy zainteresowany mógł go użyć. Cieszyć się!

using System.Threading;
using System.Windows.Forms;

public class WebProcessor
{
    private string GeneratedSource{ get; set; }
    private string URL { get; set; }

    public string GetGeneratedHTML(string url)
    {
        URL = url;

        Thread t = new Thread(new ThreadStart(WebBrowserThread));
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
        t.Join();

        return GeneratedSource;
    }

    private void WebBrowserThread()
    {
        WebBrowser wb = new WebBrowser();
        wb.Navigate(URL);

        wb.DocumentCompleted += 
            new WebBrowserDocumentCompletedEventHandler(
                wb_DocumentCompleted);

        while (wb.ReadyState != WebBrowserReadyState.Complete)
            Application.DoEvents();

        //Added this line, because the final HTML takes a while to show up
        GeneratedSource= wb.Document.Body.InnerHtml;

        wb.Dispose();
    }

    private void wb_DocumentCompleted(object sender, 
        WebBrowserDocumentCompletedEventArgs e)
    {
        WebBrowser wb = (WebBrowser)sender;
        GeneratedSource= wb.Document.Body.InnerHtml;
    }
}

questionAnswers(3)

yourAnswerToTheQuestion