Web Scraping con scrapy y regex
Tags: scrapy, regex, json, spanish
Published: 2022-07-06 13:58:01

## Visión General
En este post mostrare una manera de usar regex en un proyecto de scrapy coon CrawlerProcess, tomando como ejemplo el sitio web pagina12.com.ar
## Requirements
las librerias utilizadas en este proyecto son las siguientes
`Scrapy==2.6.1
scrappy-user-agents=0.1.1
`
## Primero crearemos el código base de la Spider

- empezamos creando la clase de nuestra spider llamada PaginaDoceSpider que hereda de scrapy.Spider

- le damos el nombre 'pagina_doce'

- como solo tenemos un url se la pasamos directamente a scrapy.Request como string y el callback lo dirigimos a nuestro segundo metodo parse_frontpage donde parseamos la pagina
    - url = "https://www.pagina12.com.ar"
    - callback = self.parse_frontpage
por ahora en el metodo parse_frontpage que recibe una response solo creamos una lista vacia y con el cual generaremos un json con los valores de esa lista

```python
#importamos los modulos necesarios
import scrapy
from scrapy.crawler import CrawlerProcess

#creamos la clase de nuestra spider
class PaginaDoceSpider(scrapy.Spider):
	name = 'pagina_doce'
	def start_requests(self):
		yield scrapy.Request(url="https://pagina12.com.ar",callback=self.parse_front_page)
	def parse_frontpage(self, response):
		links = []#aqui almacenaremos los selectores que agregaremos al json
		yield{'links': links} #generamos el json

```
## Generar Lista de Selectores
con xpath hago scraping del sitio web y con la función extract() extraigo una lista de selectores para almacenarlos en la variable hrefs

```python
hrefs = response.xpath('//a[@class="p12-dropdown-item"]/@href').extract()
for link in hrefs:
	print(link) 
```
imprimo los links del hrefs para ver que tengo mas anchors de los que queria y bueno como yo se la url de los links que necesito puedo crear una expresión regular para filtrar los hrefs.
## Utilizar Regex
Creamos una expresión regular, para utilizar en nuestra araña, a la funcion compile le pasamos una string con el regex anteponiendole una 'r', para indicar que es de forma recursiva.
Dado que el url en el que necesitamos hacer match es https://www.pagina12.com.ar/secciones  nos quedaría la expresion regular r'https:\/\/w{3}\.[a-r1-2\.\/]+secciones'
generamos el patron y lo agregamos como variable de clase a nuestra clase PaginaDoceSpider

```python
p = re.compile(r'https:\/\/w{3}\.[a-r1-2\.\/]+secciones')
```
- como los hrefs obtenidos son mas de los que queremos podemos especificar mas nuestro xpath o aplicar nuestra espresión regular

```python
links = []
for link in hrefs: # Parsear cada seccion
	if self.p.match(link):
		links.append(link)
```
filtramos los links con un if y el patron generado 'p', luego los agregamos a la lista links

## Nuestra clase final

```python
class PaginaDoceSpider(scrapy.Spider):
	name = 'pagina_doce' # Nombre del spider
    p = re.compile(r'https:\/\/w{3}\.[a-r1-2\.\/]+secciones')
    def start_requests(self):
        yield scrapy.Request(url=get_proxy_url("https://pagina12.com.ar"), callback=self.parse_frontpage)

    def parse_frontpage(self, response):
        links = []
        hrefs = response.xpath('//a[@class="p12-dropdown-item"]/@href').extract()
        for link in hrefs: # Parsear cada seccion 
            if self.p.match(link):
                links.append(link)
		yield{'links': links}
```
## Agregando settings especificos para la Spider

instanciamos un objeto process

```python
process = CrawlerProcess(settings={
        'FEED_URI': 'pagina_doce.json',
        'FEED_FORMAT': 'json',
        'DOWNLOADER_MIDDLEWARES': {
            'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
            'scrapy_user_agents.middlewares.RandomUserAgentMiddleware': 400,
        }
    })
```
con FEED_URI especificamos ej archivo output que tendra nuestra araña, con FEED_FORMAT el tipo del archivo y DOWNLOADER_MIDDLEWARES es la configuración que tenemos que poner para nuestros user agents de la libreria scrapy-user-agents
## Iniciamos el Scraping
tenemos que pasarle el nombre de nuestra clase Spider a la funcion crawl

```python
process.crawl(PaginaDoceSpider)
process.start()
```