Introducción a Python Scrapy

Que es Scrapy?

Scrapy (SKRAY-pee) es un Framework escrito en python para hacer web crawling y extraer datos estructurados los cuales pueden ser usados en un amplio rango de aplicaciones.

 

Scrapy en un principio fue diseñado para hacer web scraping pero actualmente puede ser usado para extraer datos usando API's o como un web crawler de propósito general

Web Crawling

 

Web crawling o web crawler algunas veces llamado spider, es un robot de internet(internet bot) usado típicamente para navegar en la WWW e indexar sitios.

Web Scraping

Es una tecnica en la cual un programa de computador extrae datos en formato comprensible para humanos y  lo procesa, este lo realiza usando el protocolo HTTP o HTTPS

Instalación y Configuración

Scrapy esta escrito en Python y depende de unos pocos paquetes de Python entre otros:

 

  • lxml, un eficiente XML y HTML parser
  • parsel, una librería para la extracción de HTML/XML data
  • w3lib, un helper multiproposito para lidiar con URLs y web encodings de paginas web
  • twisted, framework de networking asincrono  
  • cryptography y pyOpenSSL, para lidiar con varias necesidades de seguridad a nivel de redes

     

$ pip install Scrapy

 

Crear una spider para scrapear todos los artículos en las categorías de Electrical, Engineering Software y Wireless Modules & Adapters en http://uk.farnell.com/.

Deberá navegar por el árbol de categorías de productos (por ejemplo: Wireless Modules & Adapters / RF Modules / RF Power) hasta el nivel más bajo y analizarlo por producto.

 

Si un producto no tiene información para un campo en especifico omitir el campo.

EJERCICIO

Campos

  • url: (string) Url del producto
  • brand: (string) Marca del Producto
  • title (string) Titulo que esta en el head
  • unit_price: (float) Precio del producto
  • tariff_number (string): Codigo del producto
  • origin_country (string): País de origen
  • primary_image_url: (string) URL de la imagen principal
  • trail: (string list) Arreglos de

EJERCICIO

.
├── farnell
│   ├── __init__.py
│   ├── items.py # definición de los items
│   ├── middlewares.py # definición de los middleware
│   ├── pipelines.py # definición de los pipelines
│   ├── settings.py # archivo de configuración
│   └── spiders # aqui van a ir todos los spiders
│       ├── __init__.py
└── scrapy.cfg # archivo configuración del deploy
$ scrapy startproject farnell

SPIDER

  • name: Todo spider debe tener un name asociado el cual se usara al momento de correrlo, este nombre es único dentro del proyecto.
  • allowed_domains: Es una lista opcional de URL's con los dominios el los cuales al spider le esta permitido hacer el crawling.
  • start_urls: Una lista de las URL's las cuales el spider iniciara a hacer crawling, las primeras paginas descargadas son las especificadas en esta lista.
  • parse: Este es el default callback metodo usado por Scrapy para procesar los responses(respuestas), cuando los request no especifiquen un callback. Este metodo retorna  un iterable de request y/o un dict de Items
import scrapy


class FarnellSpider(scrapy.Spider):
    """
        Spider to crawl the URLS of the Electrical, Engineering Software,
        and Wireless Modules & Adapters categories of http://uk.farnell.com/
    """
    
    name = 'farnell'
    start_urls = [
        'http://uk.farnell.com/c/electrical',
        'http://uk.farnell.com/c/engineering-software',
        'http://uk.farnell.com/c/wireless-modules-adaptors'
    ]
    
    def parse(self, response):
        links = response.xpath('//nav[@class="filterCategoryLevelOne"]//a/@href').extract()
        for url in links:
            yield Request(url, callback=self.parse_subcategory, dont_filter=True)

    ...

SPIDER

SPIDER GENERICOS

Scrapy cuenta con los siguientes spiders genéricos:

 

  • CrawlSpider

  • XMLFeedSpider

  • CSVFeedSpider

  • SitemapSpider

mas información:

https://docs.scrapy.org/en/latest/topics/spiders.html

SELECTORES

La tarea mas comun que se realiza cuando se hace web scraping es la extracion de datos.

 

Scrapy cuenta con su propio mecanismo para la extracción de datos y se llaman selector(selectores) porque seleccionan ciertas partes de los documentos HTML especificadas ya sea por expresiones XPath o CSS.

 

XPath es un lenguaje para selección de nodos en XML el cual también puede ser usado en HTML.

 

https://docs.scrapy.org/en/latest/topics/selectors.html

SELECTORES

    def parse(self, response):
        # usando XPath
        
        links = response.xpath('//nav[@class="filterCategoryLevelOne"]//a/@href').extract()
        for url in links:
            yield Request(url, callback=self.parse_subcategory, dont_filter=True)
    def parse(self, response):
        # usando XPath
        
        links = response.css('nav[@class="filterCategoryLevelOne"]::a::attr(href)').extract()
        for url in links:
            yield Request(url, callback=self.parse_subcategory, dont_filter=True)

ITEMS

El principal objetivo de hacer web scraping es poder extrar datos estructurados de fuentes no estructuradas, tipicamente sitios o paginas web. 

 

Para esto Scrapy nos provee con la Clase Item, el cual nos permite almacenar los datos. Esta Clase no es mas que una estructura de datos tipo Python Dict, donde podremos definir los campos disponibles.

import scrapy


class FarnellItem(scrapy.Item):
    url = scrapy.Field()
    brand = scrapy.Field()
    title = scrapy.Field()
    unit_price = scrapy.Field()
    overview = scrapy.Field()
    information = scrapy.Field()
    manufacturer = scrapy.Field()
    manufacturer_part = scrapy.Field()
    tariff_number = scrapy.Field()
    origin_country = scrapy.Field()
    files = scrapy.Field()
    file_urls = scrapy.Field()
    image_urls = scrapy.Field()
    primary_image_url = scrapy.Field()
    trail = scrapy.Field()

ITEMS

ITEMS PIPELINES

Luego de que un item ha sido scrapeado por el spider es enviado al Pipeline el cual lo procesa en varios componentes que son ejecutados secuencialmente.

 

Los usos típicos de un Pipeline son

  • Validar la data Scrapeada
  • Chequear duplicados y elimiarlos
  • Almacenar el Item scrapeado en una BD o escribirlo en un archivo.

 

 

ITEMS PIPELINES

import json


class FarnellPipeline(object):
    
    def open_spider(self, spider):
        self.file = open('products.jl', 'w')
    
    def close_spider(self, spider):
        self.file.close()
    
    def process_item(self, item, spider):
        line = json.dumps(dict(item)) + "\n"
        self.file.write(line)
        return item

Veamos Scrapy en Acción 

scrapy

By Guillermo Alvarez