Есть ли способ просмотреть сгенерированный источник веб-страницы (код после всех вызовов 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;
}
}