Un acercamiento al proceso de extracción y manipulación de datos con scrapy.
Tags: python, datascience, spanish, beginners
Published: 2022-08-09 02:09:00

## Vision General

En este blog hare web scraping con un solo script utilizando scrapy y crawlerprocess, generando así un csv. Limpiaré los datos obtenidos y crearé una gráfica simple con ellos.


### Haciendo el web scraping
Iniciamos la spider, vamos a escraperar el sitio books.toscrape.com
```python
class BooksSpider(scrapy.Spider):
    name = "books_spider"
    def start_requests(self):
        yield scrapy.Request(url="http://books.toscrape.com/",callback=self.parse)
```
Parseamos los datos de la página con xpath
```python
    def parse(self, response):
        t = response.xpath('//article[@class="product_pod"]/h3/a/text()').extract()
        p = response.xpath('//article[@class = "product_pod"]/div[@class="product_price"]/p[@class="price_color"]/text()').extract()
        a = response.xpath('//article[@class = "product_pod"]/div[@class="product_price"]/p[contains(@class,"instock")]/text()').extract()
```
A continuación una forma correcta de generar un csv, con un for recorrer las listas creadas en el paso anterior y hare una prelimpieza de estos datos con .strip() que eliminara los espacios restantes.
```python
        for i in range(len(t)):
            yield {'title': t[i].strip(),'price': p[i].strip(),'availability': a[i].strip()}

```
### Generamos el csv
indicamos que el archivo de salida tendra el formato csv y se llamara books.csv
```python

process = CrawlerProcess(settings={
    'FEED_FORMAT': 'csv',
    'FEED_URI': 'books.csv',
    'DOWNLOADER_MIDDLEWARES': {#esta configuracion es para user agents
            
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
            'scrapy_user_agents.middlewares.RandomUserAgentMiddleware': 400,
        },

})
process.crawl(BooksSpider)
process.start()
```

### utilizando el jupyter notebook

importamos las librerias que utilizaremos que son: pandas y numpy
```python
import numpy as np
import pandas as pd

```
leemos el csv y vemos los primeros 5 elementos con el metodo .head()
```python
df = pd.read_csv("books.csv") 
df.head()
```

veemos que algunas filas no tiene todos sus datos asi que inspeccionamos el csv con .isna que nos devuelve true si faltan datos y tambien ponemos .any() para ver si faltan datos en cada columna

```python
df.isna().any()
```
solo faltan datos en availability que indica si hay o no stock, vamos a llenar los datos faltantes poniendo que no hay stock

```python
df.fillna("Not in stock")
```

### Graficando

importamos el submodulo pyplot
```python
import matplotlib.pyplot as plt
```
Ahora queremos graficar el precio y la disponibilidad pero la columna "availability" es de tipo string asi que la mapearemos a valores numéricos indicando que si hay stock vale 1 y si no 0
```python
df["cantidad_disponible"] = df["availability"].map({"In stock": 1,"Not in stock":0,np.nan:0})
```
Generamos la grafica indicando que el precio estará en la abscisa x y la cantidad disponible en la abscisa, donde haya datos lo marcaremos con circulo "o", indicamos que la grafica sera de color azul con color = "b" y el estilo de la linea sera dasheado
```python
fig, ax = plt.subplots()
ax.plot(df["price"],df["cantidad_disponible"],color="b",marker="o",linestyle="--")

```
Ahora agregaremos labels y un título al gráfico
```python
ax.set_xlabel("precio (en euros)")
ax.set_ylabel("disponibilidad")
ax.set_title("precio de libros")
plt.xticks(rotation=90)
plt.show() 
```

si quieren pueden ver mi deepnote con el codigo de pandas y matplotlib [Aqui el código](https://deepnote.com/workspace/karencofre-79c2-1348d886-cab9-4933-a2f7-ba8a759d7b39/project/primer-proyecto-con-pandas-75d90d60-ac45-4120-8283-c65ba47aad3a/%2Fnotebook.ipynb)