Saltar al contenido

Arrastrando la web con Python y Scrapy

Ahora que has instalado Scrapy en tu sistema, vamos a saltar a un código de ejemplo simplista. Como se discutió anteriormente, en la Introducción, estaremos raspando la página de la lista de productos de Zappos para las palabras clave zapatillas de hombre que está disponible en forma paginada.

Paso 1: Iniciar un nuevo proyecto

Dado que Scrapy es un marco, necesitamos seguir algunas normas del marco. Para crear un nuevo proyecto en Scrapy, usa el comando startproject . He nombrado mi proyecto tutorial .

Arrastrando la web con Python y Scrapy
Arrastrando la web con Python y Scrapy
1proyecto de inicio de proyecto de scrapy tutorial

Shell

Esto creará un directorio de tutoriales con los siguientes contenidos:

12345678910tutorial├─── scrapy.cfg -- despliegue el archivo de configuración de scrapy project└── tutorial -- su módulo de proyecto de scrapy. ├── __init__.py -- inicializador de módulo(archivo vacío) ├── items.py -- definición del elemento del proyecto archivo py ├── middlewares.py -- archivo py del proyecto middleware ├── pipelines.py -- archivo py del proyecto pipeline ├── settings.py -- archivo py del proyecto └── arañas -- directorio donde se guardan las arañas ├── __init__.py

docs

Paso 2: Analizar el sitio web

El siguiente paso importante al hacer el Scraping es analizar el contenido de la página web que se quiere desechar, es identificar cómo se puede recuperar la información del texto HTML examinando la singularidad en el elemento deseado.

Para inspeccionar la página en el Chrome, abre las Herramientas para desarrolladores haciendo clic con el botón derecho del ratón en la página.

En este ejemplo, pretendemos raspar toda la información sobre el producto de la lista de productos. Toda la información del producto está disponible entre las etiquetas del artículo . El ejemplo de diseño HTML de un producto (artículo) es:

1234567891011121314151617181920212223242526<article imgsrc="PRODUCTO IMG SRC HERE "alt="alt tag"--> -->spandjdj;;/div;³³³³³"div;³³³">botón /span>/pÏ...²;pitemprop="nombre"²;NOMBRE DEL PRODUCTO AQUÍ</pÏ...²;span;²;PRECIO DEL PRODUCTO AQUÍ</span; spanitemprop="aggregateRating "data-star-rating="CALIFICACIÓN DEL PRODUCTO AQUÍ</pre>
html

Del fragmento de código HTML anterior, vamos a raspar las siguientes cosas de cada producto:

  • Nombre del producto
  • Producto de
  • Precio del producto
  • Estrellas del producto
  • Imagen del producto url

Paso 3: Crear nuestra primera araña

Ahora vamos a crear nuestra primera araña. Para crear una nueva araña, puedes usar el comando genspider que toma un argumento de nombre de la araña y url de inicio .

1scrapy genspider zappos www.zappos.com

Shell

Después de ejecutar el comando anterior, notarás que se ha creado un nuevo archivo .py en la carpeta de tu araña.

En ese archivo de la pitón araña, verás una clase llamada ZapposSpider que hereda la clase scrapy.Spider y contiene un método llamado parse que discutiremos en el siguiente paso.

1234567891011import scrapyclassZapposSpider(scrapy.Spider): name =$0027zappos$0027 allowed_domains =[$0027www.zappos.com$0027] start_urls =[$0027http://www.zappos.com/$0027]defparse(self, response):pass

pitón

Para ejecutar una araña, puedes usar el comando crawl o el comando runspider .

El comando crawl toma el nombre de la araña como argumento:

1scrrapy crawl zappos

Shell

O puedes usar el comando runspider . Este comando tomará la ubicación del archivo de la araña.

1scrapy runspider tutorial/spiders/zappos.py

Shell

Después de ejecutar cualquiera de los comandos anteriores, verás la salida en la terminal mostrando algo como esto:

12345678910111213141516171819202122232019-06-17 15:45:11 [scrapy.utils.log] INFO: Scrapy 1.6.0 iniciado (bot: tutorial)2019-06-17 15:45:11 [scrapy.utils.log] INFO: Versiones: lxml 4.3.4.0, libxml2 2.9.9, cssselect 1.0.3, parsel 1.5.1, w3lib 1.20.0, Twisted 19.2.1, Python 3.6.7 (por defecto, Oct 222018, 11:32:17) - [GCC 8.2.0], pyOpenSSL 19. 0.0 (OpenSSL 1.1.1c 28 de mayo de 2019), criptografía 2.7, Plataforma Linux-4.18.0-21-generic-x86_64-con-Ubuntu-18.04-bionic2019-06-17 15:45:11 [scrapy.crawler] INFO: Ajustes anulados: {$0027NOMBRE_BOT$0027:$0027tutorial$0027, $0027MÓDULO_NUEVO$0027:$0027tutorial.arañas$0027, $0027ROBOTSTXT_OBEY$0027: Cierto, $0027SPIDER_MODULES$0027:[$0027tutorial.spiders$0027]}2019-06-17 15:45:11 [scrapy.extensions.telnet] INFO: Contraseña de Telnet: 8ddf42dffb5b3d2f2019-06-17 15:45:11 [scrapy.middleware] INFO: Extensiones habilitadas:[...]2019-06-17 15:45:11 [scrapy.middleware] INFO: Descargador de middlewares habilitado:[...]2019-06-17 15:45:11 [scrapy.middleware] INFO: Activado spider middlewares:[...]2019-06-17 15:45:11 [scrapy.middleware] INFO: Activado tuberías de artículos:[]2019-06-17 15:45:11 [scrapy.core.engine] INFO: Spider abierto2019-06-17 15:45:11 [scrapy.extensions.logstats] INFO: Arrastrado 0 páginas (a 0 páginas/min), raspado 0 artículos (a 0 artículos/min)2019-06-17 15:45:11 [scrapy.extensions.telnet] INFO: Consola de telnet escuchando en 127.0.0.1:60232019-06-17 15:45:13 [scrapy.core.engine] DEBUG: Crawled (404)<GET https://www.zappos.com/robots.txt>(referer: None)2019-06-17 15:45:13 [scrapy.core.engine] DEBUG: Crawled (200)<GET https://www.zappos.com/>(referer: None)2019-06-17 15:45:13 [scrapy.core.engine] INFO: Cerrando la araña (terminado)2019-06-17 15:45:13 [scrapy.statscollectors] INFO: Dumping Scrapy estadísticas:{...}2019-06-17 15:45:13 [scrapy.core.engine] INFO: Araña cerrada (terminada)

Shell

Paso 4: Extracción de los datos de la página

Ahora, escribamos nuestro método de análisis . Antes de saltar al método de parse, tenemos que cambiar el start_url a la URL de la página web, que deseamos raspar.

Utilizaremos selectores CSS para esta guía, ya que CSS es la opción más fácil de iterar sobre los productos. El otro selector que se utiliza comúnmente es el selector XPath . Para obtener más información sobre los selectores Scrapy, consulte esta documentación.

Como se ha mencionado anteriormente, en el paso 2, mientras inspeccionamos los elementos de la página web cada producto se envuelve en una etiqueta de artículo . Por lo tanto, tenemos que pasar por cada etiqueta de artículo y luego extraer más información del producto del objeto del producto.

El objeto producto tiene toda la información relativa a cada producto.podemos utilizar además el selector del objeto producto para encontrar información sobre el producto. Intentemos extraer sólo el nombre del producto, de cada producto de la primera página.

1234567891011121314# -*- codificación: utf-8 -*-importar clase de desguaceZapposMenShoesSpider(scrapy.Spider): nombre ="zappos" start_urls =[$0027https://www.zappos.com/men-running-shoes$0027] allowed_domains =[$0027www. zappos.com$0027]defparse(self, response):for product in response.css("article"):yield{"name": product.css("p[itemprop=$0027name$0027]::text").extract_first()}

pitón

Notarán que en el código anterior están sucediendo las siguientes cosas:

  • Usamos el selector como p[itemprop=$0027nombre$0027] para obtener el nombre del producto. Dice, "Hey encuentra la etiqueta p que tiene el atributo como itemprop y que lo establece para nombrar desde el objeto del producto".
  • Añadimos ::texto a nuestro selector para el nombre porque queremos extraer el texto entre las etiquetas adjuntas. Se llama pseudo-selector CSS.
  • Llamamos extract_first() al objeto devuelto por product.css (CSS SELECTOR) porque sólo queremos el primer elemento que coincide con el selector. Esto nos dará una cadena, en lugar de una lista de elementos, que puede coincidir con otros patrones CSS similares.

Guarda el archivo de la araña y vuelve a pasar el rascador:

1scrrapy crawl zappos

Shell

Esta vez, verá aparecer en la salida los nombres de todos los productos (100) que fueron listados en la primera página:

123456789101112......{$0027nombre$0027:$0027Movimiento 7$0027}2019-06-18 00:09:27 [raspador.núcleo.raspador] DEBUG: Raspado de https://www.zappos.com/men-running-shoes>{$0027nombre$0027:$0027Destino 5$0027}2019-06-18 00:09:27 [raspado.núcleo.raspador] DEBUG: Raspado de https://www.zappos.com/men-running-shoes>{$0027nombre$0027:$0027Gravedad 8$0027}2019-06-18 00:09:27 [raspado.núcleo.raspador] DEBUG: Raspado de https://www.zappos.com/men-running-shoes>{$0027nombre$0027:$0027Distancia 8$0027}2019-06-18 00:09:27 [raspado.núcleo.raspador] DEBUG: Raspado de https://www.zappos.com/men-running-shoes>200;.....

Shell

Ahora, ampliemos nuestro diccionario de rendimiento añadiendo precio, estrellas, por, URL de la imagen, etc.

  • por: Para extraer el producto por de un objeto de producto. Se puede utilizar el selector de texto p[itemprop=$0027brand$0027] span[itemprop=$0027name$0027]::que dice que desde el objeto producto, se encuentra la etiqueta p que tiene un atributo llamado itemprop que lo establece como marca y que tiene un elemento hijo span con el atributo llamado itemprop y el valor del atributo llamado name.
  • precio: Para el precio, se puede usar el selector de p span::texto. Observe que tenemos dos resultados de coincidencia para el selector anterior, así que tenemos que usar el segundo o coincidir en el primer índice.
  • estrellas: La estrella total de un producto puede ser extraída de un valor de atributo. El selector será p span[itemprop=$0027aggregateRating$0027]::attr($0027data-star-rating$0027), dice que, en el objeto producto, se encuentra la etiqueta p que tiene el elemento hijo span y tiene el atributo llamado itemprop que se establece en aggregateRating. Y luego extraer el valor del atributo de data-star-rating.
  • url de la imagen: Para extraer el atributo src de la etiqueta img, usaremos el selector como div span img::attr($0027src$0027).
123456789101112131415161718192021# -*- codificación: utf-8 -*-importar clase de desguaceZapposMenShoesSpider(scrapy.Spider): nombre ="zappos" start_urls =[$0027https://www.zappos. com/men-running-shoes$0027] allowed_domains =[$0027www.zappos.com$0027]defparse(self, response):for product in response.css("article"):yield{"name": product.css("p[itemprop=$0027name$0027]::text"). extract_first(), "by": producto.css("p[itemprop=$0027marca$0027] span[itemprop=$0027nombre$0027]::texto").extract_first(), "precio": producto.css("p span::texto").extract()[1], "estrellas": producto. css("p span[itemprop=$0027aggregateRating$0027]::attr($0027data-star-rating$0027)").extract_first(), "img-url": producto.css("div span img::attr($0027src$0027)").extract_first()}

pitón

Esta vez verás que toda la información de cada producto que se enumeró en la primera página apareció en la salida:

123456789101112.....{$0027nombre$0027:$0027Movimiento 7$0027, $0027por$0027:$0027Newton Running$0027, $0027precio$0027:$0027$131.25$0027, $0027estrellas$0027:$00274$0027, $0027img-url$0027:$0027https://m.media-amazon.com/images/I/81e878wBGeL._AC_SX255_.jpg$0027}2019-06-18 00:36:41 N[scrapy.core.scraper] DEBUG: Raspado de https://www.zappos.com/men-running-shoes>{$0027nombre$0027:$0027Destino 5$0027, $0027por$0027:$0027Newton Running$0027, $0027precio$0027:$0027140.00$0027, $0027estrellas$0027: Ninguno, $0027img-url$0027:$0027https://m.media-amazon.com/images/I/81nVby4s0lL._AC_SX255_.jpg$0027}2019-06-18 00:36:41 N[scrapy.core.scraper] DEBUG: Raspado de https://www.zappos.com/men-running-shoes>{$0027nombre$0027:$0027Gravedad 8$0027, $0027por$0027:$0027Newton Running$0027, $0027precio$0027:$0027$175.00$0027, $0027estrellas$0027: Ninguna, $0027img-url$0027:$0027https://m.media-amazon.com/images/I/81-iMPpgxrL._AC_SX255_.jpg$0027}2019-06-18 00:36:41 N[scrapy.core.scraper] DEBUG: Raspado de https://www.zappos.com/men-running-shoes>{$0027nombre$0027:$0027Distancia 8$0027, $0027por$0027:$0027Newton Running$0027, $0027precio$0027:$0027155.00$0027, $0027estrellas$0027:$00275$0027, $0027img-url$0027:$0027https://m.media-amazon.com/images/I/81PT5DJEVCL._AC_SX255_.jpg$0027}2019-06-18 00:36:41 [scrapy.core.scraper] DEBUG: Raspado de https://www.zappos.com/men-running-shoes>.....

Shell

Para preservar la salida en un archivo, puedes usar la bandera -o seguida del nombre del archivo mientras corres la araña.

Scrapy le permite exportar los datos extraídos a varios formatos de archivo diferentes. Algunas de las exportaciones de archivos comúnmente utilizadas son (véase):

Por ejemplo, exportemos los datos a un archivo CSV .

1 scrapy crawl zappos -o zappos.csv

Shell

Paso 5: Arrastrarse por múltiples páginas

Hemos extraído con éxito productos para la primera página. Ahora, extendamos nuestra araña para que navegue a todas las páginas disponibles para la palabra clave dada buscando el URL de la siguiente página.

Notará un enlace Next Page al final de la página

que tiene un elemento como el siguiente:

123<a>Next<!-- -- --;span>; Page</span>

html

Puedes tomar la URL de la siguiente página del atributo href de una etiqueta que tiene otro atributo único, llamado rel , que es siguiente para este elemento.

Por lo tanto, el selector de CSS para agarrar el mismo será: a[rel=$0027next$0027]::attr($0027href$0027)

Modifique su código de la siguiente manera:

12345678910111213141516171819202122232425262728293031# -*- codificación: utf-8 -*-importar clase de desguaceZapposMenShoesSpider(scrapy.Spider): nombre ="zappos_p" start_urls =[$0027https://www.zappos.com/men-running-shoes$0027] allowed_domains =[$0027www. zappos.com$0027]defparse(self, response):for product in response.css("article"):yield{"name": product.css("p[itemprop=$0027name$0027]::text").extract_first(), "by": product.css("p[itemprop=$0027brand$0027] span[itemprop=$0027name$0027]::text"). extract_first(), "precio": producto.css("p span::texto").extract()[1], "estrellas": producto.css("p span[itemprop=$0027aggregateRating$0027]::attr($0027data-star-rating$0027)").extract_first(), "img-url": producto.css("div span img::attr($0027src$0027)"). extract_first()} next_url_path = response.css("a[rel=$0027next$0027]::attr($0027href$0027)").extract_first()if next_url_path:yield scrapy.Request( response.urljoin(next_url_path), callback=self.parse )

pitón

Notarán que en el código anterior hemos añadido dos nuevas declaraciones.

  • La primera sentencia tomará la siguiente página URL, si existe, la cual almacenaremos en la variable next_url_path.
  • La segunda declaración comprobará si el next_url_path existe o no. Si existe, entonces simplemente llamamos al método self.parse con la nueva URL de la página que obtuvimos.

Por último, puedes ejecutar tu araña mencionando el archivo de salida:

1 scrapy crawl zappos -o zappos.csv

Shell