una termine que pagina mostrar mientras funcion esperar ejecutar despues cargar carga automaticamente asincrona antes c# .net screen-scraping

c# - pagina - esperar que termine una funcion javascript



Ver fuente generada(después de AJAX/JavaScript) en C# (3)

¿Hay una manera de ver la fuente generada de una página web (el código después de todas las llamadas AJAX y las manipulaciones de DOM de JavaScript) desde una aplicación C # sin abrir un navegador desde el código?

Ver la página inicial usando un objeto WebRequest o WebClient funciona bien, pero si la página utiliza JavaScript de forma extensiva para modificar el DOM en la carga de la página, entonces no proporcionan una imagen precisa de la página.

He intentado usar los marcos de prueba de Selenium y Watin UI y funcionan perfectamente, suministrando la fuente generada tal como aparece una vez que se completan todas las manipulaciones de JavaScript. Desafortunadamente, lo hacen abriendo un navegador web real, que es muy lento. He implementado un servidor de selenio que descarga este trabajo a otra máquina, pero todavía hay un retraso sustancial.

¿Hay una biblioteca .Net que cargará y analizará una página (como un navegador) y escupirá el código generado? Claramente, Google y Yahoo no abren los navegadores para cada página que quieren arañar (por supuesto que pueden tener más recursos que yo ...).

¿Existe tal biblioteca o estoy fuera de suerte a menos que esté dispuesto a analizar el código fuente de un navegador de código abierto?

SOLUCIÓN

Bueno, gracias a todos por su ayuda. Tengo una solución de trabajo que es 10 veces más rápida que Selenium. ¡Cortejar!

Gracias a este antiguo artículo de beansoftware pude usar el control System.Windows.Forms.WebBrowser para descargar la página y analizarla, luego darles la fuente generada. A pesar de que el control está en Windows.Forms, aún puede ejecutarlo desde Asp.Net (que es lo que estoy haciendo), solo recuerde agregar System.Window.Forms a las referencias de su proyecto.

Hay dos cosas notables sobre el código. Primero, el control WebBrowser se llama en un nuevo hilo. Esto se debe a que debe ejecutarse en un apartamento de un solo hilo .

En segundo lugar, la variable GeneratedSource se establece en dos lugares. Esto no se debe a una decisión de diseño inteligente :) Todavía estoy trabajando en ello y actualizaré esta respuesta cuando termine. wb_DocumentCompleted () se llama varias veces. Primero cuando se descarga el HTML inicial, y luego nuevamente cuando se completa la primera ronda de JavaScript. Desafortunadamente, el sitio que estoy raspando tiene 3 etapas de carga diferentes. 1) Cargar HTML inicial 2) Hacer la primera ronda de manipulación de DOM de JavaScript 3) hacer una pausa de medio segundo y luego hacer una segunda ronda de manipulación de JS DOM.

Por alguna razón, la segunda ronda no es causada por la función wb_DocumentCompleted (), pero siempre se detecta cuando wb.ReadyState == Complete. Entonces, ¿por qué no eliminarlo de wb_DocumentCompleted ()? Todavía no estoy seguro de por qué no está atrapado allí y ahí es donde el artículo del software de cuentas recomendó ponerlo. Voy a seguir investigándolo. Solo quería publicar este código para que cualquiera que esté interesado pueda usarlo. ¡Disfrutar!

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


La mejor manera es usar PhantomJs . Eso es genial. (muestra de eso es el Article ).

Mi solución es parecida a esta:

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


Teóricamente sí, pero, en la actualidad, no.

No creo que haya un producto o un proyecto OSS que haga esto. Tal producto necesitaría tener su propio intérprete javascript y ser capaz de emular con precisión el entorno de tiempo de ejecución y las peculiaridades de cada navegador que admite.

Dado que necesita algo que emule con precisión el entorno del servidor + navegador para producir el código final de la página, a largo plazo, creo que usar una instancia del navegador es la mejor manera de generar la página con precisión en su estado final. Esto es especialmente cierto cuando considera que, una vez que se completa la carga de la página, las fuentes de la página aún pueden cambiar con el tiempo en el navegador desde AJAX / javascript.


posiblemente esté usando una instancia de un navegador (en su caso: el control ie). Puedes usarlo fácilmente en tu aplicación y abrir una página. El control lo cargará y procesará cualquier javascript. Una vez hecho esto, puede acceder al objeto dom de controles y obtener el código "interpretado".