scraping follow example python screen-scraping scrapy

python - follow - Scrapy, desechando datos dentro de un Javascript



scrapy vs beautifulsoup (2)

Cuando abra https://www.mcdonalds.com.sg/locate-us/ en el navegador que elija, abra la herramienta "inspeccionar" (es de esperar que tenga una, por ejemplo, Chrome o Firefox) y busque "Red "pestaña.

Puede filtrar aún más los eventos "XHR" (XMLHttpRequest), y verá una solicitud POST a https://www.mcdonalds.com.sg/wp-admin/admin-ajax.php con este cuerpo

action=ws_search_store_location&store_name=0&store_area=0&store_type=0

La respuesta a esa solicitud POST es un objeto JSON con toda la información que desea

import json import pprint ... class MySpider(BaseSpider): ... def parse_json(self, response): js = json.loads(response.body) pprint.pprint(js)

Esto daría como resultado algo como:

{u''flagicon'': u''https://www.mcdonalds.com.sg/wp-content/themes/mcd/images/storeflag.png'', u''stores'': {u''listing'': [{u''address'': u''678A Woodlands Avenue 6<br/>#01-05<br/>Singapore 731678'', u''city'': u''Singapore'', u''id'': 78, u''lat'': u''1.440409'', u''lon'': u''103.801489'', u''name'': u"McDonald''s Admiralty", u''op_hours'': u''24 hours<br>/r/nDessert Kiosk: 0900-0100'', u''phone'': u''68940513'', u''region'': u''north'', u''type'': [u''24hrs'', u''dessert_kiosk''], u''zip'': u''731678''}, {u''address'': u''383 Bukit Timah Road<br/>#01-09B<br/>Alocassia Apartments<br/>Singapore 259727'', u''city'': u''Singapore'', u''id'': 97, u''lat'': u''1.319752'', u''lon'': u''103.827398'', u''name'': u"McDonald''s Alocassia", u''op_hours'': u''Daily: 0630-0100'', u''phone'': u''68874961'', u''region'': u''central'', u''type'': [u''24hrs_weekend'', u''drive_thru'', u''mccafe''], u''zip'': u''259727''}, ... {u''address'': u''60 Yishuan Avenue 4 <br/>#01-11<br/><br/>Singapore 769027'', u''city'': u''Singapore'', u''id'': 1036, u''lat'': u''1.423924'', u''lon'': u''103.840628'', u''name'': u"McDonald''s Yishun Safra", u''op_hours'': u''24 hours'', u''phone'': u''67585632'', u''region'': u''north'', u''type'': [u''24hrs'', u''drive_thru'', u''live_screening'', u''mccafe'', u''bday_party''], u''zip'': u''769027''}], u''region'': u''all''}}

Te dejo para que extraigas los campos que quieras.

En FormRequest () que envía con Scrapy, probablemente necesite agregar un encabezado "X-Request-With: XMLHttpRequest" (su navegador lo envía si observa los encabezados de solicitud en la herramienta de inspección)

Estoy utilizando scrapy para filtrar los datos de un sitio web. Sin embargo, los datos que quería no estaban dentro del html, sino que son de un javascript. Entonces, mi pregunta es:

¿Cómo obtener los valores (valores de texto) de tales casos?

Este es el sitio que estoy intentando rastrear: https://www.mcdonalds.com.sg/locate-us/

Atributos que estoy tratando de obtener: Dirección, Contacto, Horas de operación.

Si hace un "clic derecho", "ve la fuente" dentro de un navegador Chrome, verá que tales valores no están disponibles en el HTML.

Editar

Sry paul, hice lo que me dijiste, encontré admin-ajax.php y vi el cuerpo, pero ahora estoy muy atascado.

¿Cómo recupero los valores del objeto json y los almaceno en un campo variable de mi propiedad? Sería bueno, si pudieras compartir cómo hacer solo un atributo para el público y para aquellos que también comenzaron a usar scrapy.

Aquí está mi código hasta ahora

Items.py

class McDonaldsItem(Item): name = Field() address = Field() postal = Field() hours = Field()

McDonalds.py

from scrapy.spider import BaseSpider from scrapy.selector import HtmlXPathSelector import re from fastfood.items import McDonaldsItem class McDonaldSpider(BaseSpider): name = "mcdonalds" allowed_domains = ["mcdonalds.com.sg"] start_urls = ["https://www.mcdonalds.com.sg/locate-us/"] def parse_json(self, response): js = json.loads(response.body) pprint.pprint(js)

Sry por edición larga, así que en resumen, ¿cómo almaceno el valor json en mi atributo? por ejemplo

*** elemento [''dirección''] = * cómo recuperar ****

PS, no estoy seguro de si esto ayuda, pero ejecuto estos scripts en la línea cmd usando

scrapy crawl mcdonalds -o McDonalds.json -t json (para guardar todos mis datos en un archivo json)

No puedo enfatizar lo suficiente en lo agradecido que me siento. Sé que es un poco irrazonable preguntarte esto, estaremos totalmente bien incluso si no tienes tiempo para esto.


(Lo scrapy-users lista de correo de scrapy-users pero por sugerencia de Paul, lo estoy publicando aquí ya que complementa la respuesta con la interacción del comando de shell ).

En general, los sitios web que utilizan un servicio de terceros para representar la visualización de algunos datos (mapa, tabla, etc.) deben enviar los datos de alguna manera, y en la mayoría de los casos, se puede acceder a estos datos desde el navegador.

Para este caso, una inspección (es decir, explorando las solicitudes realizadas por el navegador) muestra que los datos se cargan desde una solicitud POST a https://www.mcdonalds.com.sg/wp-admin/admin-ajax.php

Entonces, básicamente tienes todos los datos que deseas en un formato json agradable listo para consumir.

Scrapy proporciona el comando de shell que es muy conveniente para el pensador con el sitio web antes de escribir la araña:

$ scrapy shell https://www.mcdonalds.com.sg/locate-us/ 2013-09-27 00:44:14-0400 [scrapy] INFO: Scrapy 0.16.5 started (bot: scrapybot) ... In [1]: from scrapy.http import FormRequest In [2]: url = ''https://www.mcdonalds.com.sg/wp-admin/admin-ajax.php'' In [3]: payload = {''action'': ''ws_search_store_location'', ''store_name'':''0'', ''store_area'':''0'', ''store_type'':''0''} In [4]: req = FormRequest(url, formdata=payload) In [5]: fetch(req) 2013-09-27 00:45:13-0400 [default] DEBUG: Crawled (200) <POST https://www.mcdonalds.com.sg/wp-admin/admin-ajax.php> (referer: None) ... In [6]: import json In [7]: data = json.loads(response.body) In [8]: len(data[''stores''][''listing'']) Out[8]: 127 In [9]: data[''stores''][''listing''][0] Out[9]: {u''address'': u''678A Woodlands Avenue 6<br/>#01-05<br/>Singapore 731678'', u''city'': u''Singapore'', u''id'': 78, u''lat'': u''1.440409'', u''lon'': u''103.801489'', u''name'': u"McDonald''s Admiralty", u''op_hours'': u''24 hours<br>/r/nDessert Kiosk: 0900-0100'', u''phone'': u''68940513'', u''region'': u''north'', u''type'': [u''24hrs'', u''dessert_kiosk''], u''zip'': u''731678''}

En resumen: en su araña debe devolver el FormRequest(...) anterior, luego en la devolución de llamada, cargue el objeto json desde response.body y finalmente para los datos de cada tienda en la lista de data[''stores''][''listing''] crea un elemento con los valores deseados.

Algo como esto:

class McDonaldSpider(BaseSpider): name = "mcdonalds" allowed_domains = ["mcdonalds.com.sg"] start_urls = ["https://www.mcdonalds.com.sg/locate-us/"] def parse(self, response): # This receives the response from the start url. But we don''t do anything with it. url = ''https://www.mcdonalds.com.sg/wp-admin/admin-ajax.php'' payload = {''action'': ''ws_search_store_location'', ''store_name'':''0'', ''store_area'':''0'', ''store_type'':''0''} return FormRequest(url, formdata=payload, callback=self.parse_stores) def parse_stores(self, response): data = json.loads(response.body) for store in data[''stores''][''listing'']: yield McDonaldsItem(name=store[''name''], address=store[''address''])