Saltar al contenido

¿Se puede usar scrapy para extraer contenido dinámico de sitios web que usan AJAX?

Por fin después de mucho batallar ya dimos con el resultado de esta cuestión que agunos usuarios de este sitio web presentan. Si quieres compartir algún detalle no dejes de aportar tu información.

Solución:

Aquí hay un ejemplo simple de scrapy con una solicitud AJAX. Veamos el sitio rubin-kazan.ru.

Todos los mensajes se cargan con una solicitud AJAX. Mi objetivo es recuperar estos mensajes con todos sus attributes (autor, fecha, …):

ingrese la descripción de la imagen aquí

Cuando analizo el código fuente de la página no puedo ver todos estos mensajes porque la página web usa tecnología AJAX. Pero puedo con Firebug de Mozilla Firefox (o una herramienta equivalente en otros navegadores) para analizar la solicitud HTTP que genera los mensajes en la página web:

ingrese la descripción de la imagen aquí

No recarga toda la página, sino solo las partes de la página que contienen mensajes. Para este propósito, hago clic en un número arbitrario de página en la parte inferior:

ingrese la descripción de la imagen aquí

Y observo la solicitud HTTP que es responsable del cuerpo del mensaje:

ingrese la descripción de la imagen aquí

Después de terminar, analizo los encabezados de la solicitud (debo citar que esta URL la extraeré de la página de origen de la sección var, vea el código a continuación):

ingrese la descripción de la imagen aquí

Y el contenido de los datos del formulario de la solicitud (el método HTTP es “Publicar”):

ingrese la descripción de la imagen aquí

Y el contenido de la respuesta, que es un archivo JSON:

ingrese la descripción de la imagen aquí

Que presenta toda la información que estoy buscando.

A partir de ahora, debo implementar todo este conocimiento en scrapy. Definamos la araña para este propósito:

class spider(BaseSpider):
    name = 'RubiGuesst'
    start_urls = ['http://www.rubin-kazan.ru/guestbook.html']

    def parse(self, response):
        url_list_gb_messages = re.search(r'url_list_gb_messages="(.*)"', response.body).group(1)
        yield FormRequest('http://www.rubin-kazan.ru' + url_list_gb_messages, callback=self.RubiGuessItem,
                          formdata='page': str(page + 1), 'uid': '')

    def RubiGuessItem(self, response):
        json_file = response.body

En parse función Tengo la respuesta para la primera solicitud. En RubiGuessItem Tengo el archivo JSON con toda la información.

Los navegadores basados ​​en Webkit (como Google Chrome o Safari) tienen herramientas de desarrollo integradas. En Chrome puedes abrirlo Menu->Tools->Developer Tools. Él Network La pestaña le permite ver toda la información sobre cada solicitud y respuesta:

ingrese la descripción de la imagen aquí

En la parte inferior de la imagen, puede ver que he filtrado la solicitud hasta XHR – estas son solicitudes hechas por código javascript.

Consejo: el registro se borra cada vez que carga una página, en la parte inferior de la imagen, el botón de punto negro conservará el registro.

Después de analizar las solicitudes y las respuestas, puede simular estas solicitudes desde su rastreador web y extraer datos valiosos. En muchos casos, será más fácil obtener sus datos que analizar HTML, porque esos datos no contienen lógica de presentación y están formateados para acceder mediante código javascript.

Firefox tiene una extensión similar, se llama firebug. Algunos argumentarán que firebug es aún más poderoso, pero me gusta la simplicidad de webkit.

Muchas veces, al rastrear, nos encontramos con problemas en los que el contenido que se muestra en la página se genera con Javascript y, por lo tanto, Scrapy no puede rastrearlo (p. ej., solicitudes de ajax, locura de jQuery).

Sin embargo, si usa Scrapy junto con el marco de prueba web Selenium, podemos rastrear cualquier cosa que se muestre en un navegador web normal.

Algunas cosas a tener en cuenta:

  • Debe tener instalada la versión Python de Selenium RC para que esto funcione, y debe haber configurado Selenium correctamente. Además, esto es solo un rastreador de plantillas. Podrías volverte mucho más loco y más avanzado con las cosas, pero solo quería mostrar la idea básica. Tal como está el código ahora, realizará dos solicitudes para cualquier URL determinada. Scrapy realiza una solicitud y Selenium realiza la otra. Estoy seguro de que hay formas de evitar esto para que posiblemente pueda hacer que Selenium haga la única solicitud, pero no me molesté en implementar eso y al hacer dos solicitudes también puede rastrear la página con Scrapy.

  • Esto es bastante poderoso porque ahora tiene todo el DOM renderizado disponible para rastrear y aún puede usar todas las funciones de rastreo agradables en Scrapy. Esto hará que el rastreo sea más lento, por supuesto, pero dependiendo de cuánto necesite el DOM renderizado, podría valer la pena esperar.

    from scrapy.contrib.spiders import CrawlSpider, Rule
    from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
    from scrapy.selector import HtmlXPathSelector
    from scrapy.http import Request
    
    from selenium import selenium
    
    class SeleniumSpider(CrawlSpider):
        name = "SeleniumSpider"
        start_urls = ["http://www.domain.com"]
    
        rules = (
            Rule(SgmlLinkExtractor(allow=('.html', )), callback='parse_page',follow=True),
        )
    
        def __init__(self):
            CrawlSpider.__init__(self)
            self.verificationErrors = []
            self.selenium = selenium("localhost", 4444, "*chrome", "http://www.domain.com")
            self.selenium.start()
    
        def __del__(self):
            self.selenium.stop()
            print self.verificationErrors
            CrawlSpider.__del__(self)
    
        def parse_page(self, response):
            item = Item()
    
            hxs = HtmlXPathSelector(response)
            #Do some XPath selection with Scrapy
            hxs.select('//div').extract()
    
            sel = self.selenium
            sel.open(response.url)
    
            #Wait for javscript to load in Selenium
            time.sleep(2.5)
    
            #Do some crawling of javascript created content with Selenium
            sel.get_text("//div")
            yield item
    
    # Snippet imported from snippets.scrapy.org (which no longer works)
    # author: wynbennett
    # date  : Jun 21, 2011
    

Referencia: http://snipplr.com/view/66998/

Reseñas y calificaciones

Tienes la opción de estimular nuestra misión escribiendo un comentario o valorándolo te damos las gracias.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *