2011-09-07 22 views
8

Necesito hacer un poco de raspado web. Después de jugar con diferentes frameworks de pruebas web, de los cuales la mayoría eran demasiado lentos (Selenium) o demasiado caídos para mis necesidades (env.js), decidí que zombie.js parecía el más prometedor, ya que usa un sólido conjunto de bibliotecas para analizar HTML y manipulación DOM. Sin embargo, me parece como si ni siquiera se admite el código Javascript básica basada en eventos como en la siguiente página web:Problemas con el raspado del sitio web usando zombie.js

<html> 
    <head> 
    <title>test</title> 
    <script type="text/javascript"> 

     console.log("test script executing..."); 
     console.log("registering callback for event DOMContentLoaded on " + document); 

     document.addEventListener('DOMContentLoaded', function(){ 
     console.log("DOMContentLoaded triggered"); 
     }, false); 

     function loaded() { 
     console.log("onload triggered"); 
     } 

    </script> 
    </head> 

    <body onload="loaded();"> 
    <h1>Test</h1> 
    </body> 
</html> 

Entonces me decidí a desencadenar estos eventos manualmente así:

zombie = require("zombie"); 

zombie.visit("http://localhost:4567/", { debug: true }, function (err, browser, status) { 

    doc = browser.document; 
    console.log("firing DOMContentLoaded on " + doc); 
    browser.fire("DOMContentLoaded", doc, function (err, browser, status) { 

    body = browser.querySelector("body"); 
    console.log("firing load on " + body); 
    browser.fire("load", body, function (err, browser, status) { 

     console.log(browser.html()); 

    }); 
    }); 

}); 

que funciona para esta página de prueba en particular. Sin embargo, mi problema es más general: quiero ser capaz de eliminar sitios más complejos basados ​​en AJAX, como una lista de amigos en Facebook (algo así como http://www.facebook.com/profile.php?id=100000028174850&sk=friends&v=friends). No es ningún problema iniciar sesión en el sitio usando zombies, pero algunos contenidos como esas listas parecen estar completamente cargados dinámicamente usando AJAX, y no sé cómo activar los controladores de eventos que inician la carga.

Hay varias preguntas que tenga con respecto a este problema:

  • Ha alguien ya implementado un raspador igualmente compleja sin necesidad de utilizar un navegador solución como selenio se controla a distancia?
  • ¿Hay alguna referencia sobre el proceso de carga de una página compleja basada en Javascript?
  • ¿Puede alguien dar consejos sobre cómo depurar un navegador real para ver lo que podría necesitar para ejecutar los manejadores de eventos de Facebook?
  • ¿Alguna otra idea sobre este tema?

De nuevo, por favor no me dirijan a soluciones que impliquen controlar un navegador real como Selenium, como yo sé. Sin embargo, lo que sí es bienvenido son sugerencias para un renderizador en memoria real como WebKit accesible desde el lenguaje de scripting Ruby, pero preferiblemente con la posibilidad de establecer cookies y, preferiblemente, cargar HTML sin procesar en lugar de generar solicitudes HTTP reales.

+0

¿Está buscando un marco de prueba de JavaScript o una herramienta de extracción de datos web? Si solo está buscando una herramienta de raspado, es posible raspar la mayoría de los sitios sin ejecutar su Javascript, incluso los pesados ​​AJAX. – chesles

+1

La pregunta es sobre raspado web. Tienes razón, a menudo es posible hacer esto sin ejecutar Js, p. emitiendo solicitudes REST de forma manual. En el caso de Facebook, raspar la versión móvil del sitio es bastante posible usando únicamente el análisis HTTP y HTML. Pero estoy interesado en una solución genérica que entienda Javascript y no requiera una instancia real del navegador. Esto parece ser posible, como lo muestran env.Js y zombie.Js, pero parece ser un problema de trucos. –

Respuesta

12

Para fines de extracción de datos, ejecutar un "navegador sin cabeza" y desencadenar eventos de JavaScript manualmente no va a ser lo más fácil de hacer. Si bien no es imposible, existen formas más simples de hacerlo.

La mayoría de los sitios, incluso los más pesados ​​AJAX, se pueden raspar sin ejecutar una sola línea de su código JavaScript. De hecho, suele ser más fácil que intentar averiguar el código de JavaScript de un sitio, que a menudo está ofuscado, minimizado y es difícil de depurar. Si tiene una comprensión sólida de HTTP comprenderá por qué: (casi) todas las interacciones con el servidor están codificadas como solicitudes HTTP, por lo tanto, si son iniciadas por Javascript, o el usuario hace clic en un enlace o código personalizado en un programa bot, no hay diferencia para el servidor. (Digo casi porque cuando Flash o applets se involucran no hay forma de saber qué datos están volando, sino que pueden ser específicos de la aplicación. Pero cualquier cosa hecha en Javascript pasará por HTTP.)

Dicho esto, es posible imitar a un usuario en cualquier sitio web usando software personalizado. Primero, debe poder ver las solicitudes HTTP sin procesar que se envían al servidor. Puede usar un servidor proxy para registrar las solicitudes realizadas por un navegador real en el sitio web de destino. Hay muchas, muchas herramientas que puede usar para esto: Charles o Fiddler son útiles, la mayoría de los dedicados screen-scraper tools tienen un proxy básico incorporado, la extensión Firebug para Firefox y Chrome tienen herramientas similares para ver solicitudes AJAX ... se entiende la idea .

Una vez que puede ver las solicitudes HTTP que se realizan como resultado de una acción particular en el sitio web, es fácil escribir un programa para imitar estas solicitudes; solo envíe las mismas solicitudes al servidor y tratará su programa como un navegador en el que se haya realizado una acción en particular.

Existen diferentes bibliotecas para diferentes idiomas que ofrecen diferentes capacidades. Para ruby, he visto mucha gente usando mechanize for ruby.

Si la extracción de datos es su único objetivo, casi siempre podrá obtener lo que necesita al imitar las solicitudes HTTP de esta manera. No se requiere Javascript

Nota - Desde que mencionaste Facebook, debo mencionar que raspar Facebook específicamente puede ser excepcionalmente difícil (aunque no imposible), porque Facebook tiene medidas para detectar el acceso automático (usan algo más que captchas); deshabilitarán una cuenta si ven actividad sospechosa proveniente de ella. Después de todo, es contra su terms of service (sección 3.2).

+1

Gracias por formular esta sofisticada respuesta a la pregunta. Ya uso Firebug y Fiddler2 para monitorear el tráfico HTTP desde y hacia los servidores web, que sin embargo no es muy útil si se usa un tema de comunicación difícil de revertir, como lo hacen muchos sitios de redes sociales. Pero incluso si es posible usar la interfaz de bajo nivel para hablar con un servidor web y extraer información, esto requerirá ajustes constantes del raspador, lo que puede llevar mucho tiempo. Env.js (que casi llegué a trabajar como quiero) muestra que, de hecho, es posible simular un navegador real mediante programación. –

+0

Es cierto, Facebook y otros sitios intentan dificultar al máximo que rasques sus sitios; ellos prefieren que uses sus API para que puedan controlar mejor a lo que accede tu programa y, por lo tanto, proteger mejor la privacidad de los usuarios. – chesles

+0

Aún así, emular a un usuario de navegación con una herramienta como Selenium parece funcionar sin problemas (excepto por la lentitud), no encontré ningún obstáculo excepto por el uso extensivo de contenido dinámico. Incluso OAuth no está protegido contra el acceso automático, la autenticación se puede programar sin ningún problema y ni siquiera requiere Javascript para funcionar. –

Cuestiones relacionadas