27 Stimmen

Ansicht des generierten Quelltextes (nach AJAX/JavaScript) in C#

Gibt es eine Möglichkeit, den generierten Quellcode einer Webseite (den Code nach allen AJAX-Aufrufen und JavaScript-DOM-Manipulationen stattgefunden haben) aus einer C#-Anwendung zu sehen, ohne einen Browser aus dem Code zu öffnen?

Anzeigen der Einstiegsseite mit einem WebRequest o WebClient Objekt funktioniert gut, aber wenn die Seite ausgiebigen Gebrauch von JavaScript macht, um das DOM beim Laden der Seite zu verändern, dann liefern diese kein genaues Bild der Seite.

Ich habe versucht, mit Selen y Watin UI-Testing-Frameworks und sie funktionieren perfekt und liefern den generierten Quellcode so, wie er nach Abschluss aller JavaScript-Manipulationen erscheint. Leider tun sie dies, indem sie einen echten Webbrowser öffnen, was sehr langsam ist. Ich habe einen Selenium-Server implementiert, der diese Arbeit auf einen anderen Rechner auslagert, aber es gibt immer noch eine erhebliche Verzögerung.

Gibt es eine .Net-Bibliothek, die eine Seite lädt und parst (wie ein Browser) und den generierten Code ausspuckt? Offensichtlich öffnen Google und Yahoo nicht für jede Seite, die sie spidern wollen, einen Browser (natürlich haben sie vielleicht mehr Ressourcen als ich...).

Gibt es eine solche Bibliothek oder habe ich kein Glück, es sei denn, ich bin bereit, den Quellcode eines Open-Source-Browsers zu sezieren?

LÖSUNG

Ich danke Ihnen allen für Ihre Hilfe. Ich habe eine funktionierende Lösung, die etwa 10X schneller als Selenium ist. Wow!

Dank dieser alter Artikel von beansoftware Ich konnte das System.Windows.Forms.WebBrowser-Steuerelement verwenden, um die Seite herunterzuladen und zu analysieren, dann geben Sie em die generierte Quelle. Auch wenn das Steuerelement in Windows.Forms ist, können Sie es immer noch von Asp.Net ausführen (was ich tue), denken Sie daran, System.Window.Forms zu Ihrem Projekt Referenzen hinzufügen.

Es gibt zwei bemerkenswerte Dinge in diesem Code. Erstens wird das WebBrowser-Steuerelement in einem neuen Thread aufgerufen. Das liegt daran, dass es auf einem Wohnung mit einem Gewinde .

Zweitens wird die Variable GeneratedSource an zwei Stellen gesetzt. Dies ist nicht auf eine intelligente Designentscheidung zurückzuführen :) Ich arbeite noch daran und werde diese Antwort aktualisieren, wenn ich fertig bin. wb_DocumentCompleted() wird mehrfach aufgerufen. Zuerst, wenn das anfängliche HTML heruntergeladen wird, dann noch einmal, wenn die erste Runde von JavaScript abgeschlossen ist. Leider hat die Website, die ich auslese, 3 verschiedene Ladephasen. 1) Laden Sie die anfängliche HTML 2) Führen Sie die erste Runde der JavaScript-DOM-Manipulation 3) Pause für eine halbe Sekunde dann tun eine zweite Runde der JS-DOM-Manipulation.

Aus irgendeinem Grund wird die zweite Runde nicht von der Funktion wb_DocumentCompleted() ausgelöst, sondern immer, wenn wb.ReadyState == Complete ist. Warum sollte man sie also nicht aus wb_DocumentCompleted() entfernen? Ich bin mir immer noch nicht sicher, warum es nicht dort abgefangen wird, wo es laut dem Beadsoftware-Artikel hingehört. Ich werde mir das weiter ansehen. Ich wollte diesen Code nur veröffentlichen, damit jeder, der daran interessiert ist, ihn verwenden kann. Viel Spaß damit!

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

4voto

Niko Punkte 5873

Es ist möglicherweise mit einer Instanz eines Browsers (in Ihrem Fall: die ie-Steuerung). Sie können leicht in Ihrer app und öffnen Sie eine Seite. das Steuerelement wird dann laden Sie es und verarbeiten alle Javascript. sobald dies geschehen ist, können Sie die Kontrollen dom-Objekt zugreifen und erhalten Sie die "interpretiert" Code.

2voto

B P . A ).

M

var page = require('webpage').create();

page.open("https://sample.com", function(){
    page.evaluate(function(){
        var i = 0,
        oJson = jsonData,
        sKey;
        localStorage.clear();

        for (; sKey = Object.keys(oJson)[i]; i++) {
            localStorage.setItem(sKey,oJson[sKey])
        }
    });

    page.open("https://sample.com", function(){
        setTimeout(function(){
         page.render("screenshoot.png") 
            // Where you want to save it    
           console.log(page.content); //page source
            // You can access its content using jQuery
            var fbcomments = page.evaluate(function(){
                return $("body").contents().find(".content") 
            }) 
            phantom.exit();
        },10000)
    });     
});

1voto

Jeff Leonard Punkte 3214

Theoretisch ja, aber gegenwärtig nicht.

Ich glaube nicht, dass es derzeit ein Produkt oder ein OSS-Projekt gibt, das dies tut. Ein solches Produkt müsste über einen eigenen Javascript-Interpreter verfügen und in der Lage sein, die Laufzeitumgebung und die Eigenheiten jedes von ihm unterstützten Browsers genau zu emulieren.

Da Sie etwas benötigen, das die Server- und Browserumgebung genau emuliert, um den endgültigen Seitencode zu erzeugen, denke ich, dass die Verwendung einer Browserinstanz auf lange Sicht der beste Weg ist, um die Seite in ihrem endgültigen Zustand genau zu erzeugen. Dies gilt insbesondere, wenn man bedenkt, dass sich die Seitenquellen nach dem Laden der Seite im Laufe der Zeit im Browser durch AJAX/Javas verändern können.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X