Просмотр сгенерированного источника (после AJAX / JavaScript) в C # - PullRequest
26 голосов
/ 20 августа 2009

Есть ли способ просмотреть сгенерированный источник веб-страницы (код после всех вызовов AJAX и манипуляций с JavaScript DOM) из приложения C # без открытия браузера из кода?

Просмотр начальной страницы с помощью объекта WebRequest или WebClient работает нормально, но если страница широко использует JavaScript для изменения DOM при загрузке страницы, то это не предоставить точное изображение страницы.

Я пытался использовать Selenium и Watin Среды тестирования пользовательского интерфейса, и они отлично работают, предоставляя сгенерированный источник таким, какой он появляется после завершения всех манипуляций JavaScript. К сожалению, они делают это, открывая настоящий веб-браузер, который работает очень медленно. Я реализовал сервер селена, который переносит эту работу на другую машину, но все еще существует существенная задержка.

Существует ли библиотека .Net, которая будет загружать и анализировать страницу (например, браузер) и выплевывать сгенерированный код? Ясно, что Google и Yahoo не открывают браузеры для каждой страницы, которую они хотят найти (конечно, у них может быть больше ресурсов, чем у меня ...).

Есть ли такая библиотека или мне не повезло, если я не желаю анализировать исходный код браузера с открытым исходным кодом?

РЕШЕНИЕ

Ну, спасибо всем за помощь. У меня есть рабочее решение, которое примерно в 10 раз быстрее, чем Selenium. Woo!

Благодаря этой старой статье от beansoftware Мне удалось использовать элемент управления System.Windows.Forms.WebBrowser, чтобы загрузить страницу и проанализировать ее, а затем выдать сгенерированный источник. Несмотря на то, что элемент управления находится в Windows.Forms, вы все равно можете запустить его из Asp.Net (что я и делаю), просто не забудьте добавить System.Window.Forms к ссылкам вашего проекта.

В коде есть две примечательные вещи. Во-первых, элемент управления WebBrowser вызывается в новом потоке. Это потому, что он должен работать в однопоточной квартире .

Во-вторых, переменная GeneratedSource установлена ​​в двух местах. Это не из-за разумного дизайнерского решения :) Я все еще работаю над этим и обновлю этот ответ, когда я закончу. wb_DocumentCompleted () вызывается несколько раз. Сначала, когда загружается исходный HTML, затем снова, когда завершается первый раунд JavaScript. К сожалению, сайт, который я очищаю, имеет 3 разных этапа загрузки. 1) Загрузите исходный HTML 2) Выполните первый раунд манипуляций с DOM JavaScript 3) Сделайте паузу на полсекунды, затем выполните второй раунд манипуляций с JS DOM.

По какой-то причине второй раунд не вызывается функцией wb_DocumentCompleted (), но он всегда перехватывается, когда wb.ReadyState == Complete. Так почему бы не удалить его из wb_DocumentCompleted ()? Я все еще не уверен, почему это не поймано там, и именно там статья о программном обеспечении рекомендовала поместить это. Я буду продолжать изучать это. Я просто хотел опубликовать этот код, чтобы любой желающий мог его использовать. Наслаждайтесь!

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

Ответы [ 3 ]

4 голосов
/ 20 августа 2009

возможно, он использует экземпляр браузера (в вашем случае: элемент управления ie). Вы можете легко использовать в своем приложении и открыть страницу. Затем элемент управления загрузит его и обработает любой javascript. как только это будет сделано, вы можете получить доступ к объекту управления dom и получить «интерпретированный» код.

2 голосов
/ 09 февраля 2016

Лучший способ - использовать PhantomJs . Замечательно. (образец этого Артикул ).

Мое решение выглядит так:

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)
    });     
});
1 голос
/ 20 августа 2009

Теоретически да, но в настоящее время нет.

Я не думаю, что в настоящее время существует продукт или проект OSS, который делает это. Такой продукт должен иметь собственный интерпретатор javascript и иметь возможность точно имитировать среду выполнения и особенности каждого поддерживаемого им браузера.

Учитывая, что вам нужно что-то, что точно имитирует среду сервер + браузер, для создания окончательного кода страницы, в долгосрочной перспективе, я думаю, что использование экземпляра браузера - лучший способ точно сгенерировать страницу в ее конечном состоянии. , Это особенно верно, если учесть, что после завершения загрузки страницы источники страницы все еще могут со временем меняться в браузере от AJAX / javascript.

...