Web scraping con python
¿Que es web scraping?
Es el proceso por el cual extraemos datos de paginas web utilizando scripts o bots que realizan requests y procesan los datos obtenidos
Contenido
Veamos juntos en este posteo la extracción de los datos de una pagina, el procesamiento de estos y grabar los mismos en 4 diferentes formatos de archivos:
- Texto
- CSV
- JSON
- Excel
Librerias
Vamos a necesitar tener instaladas las siguientes librerías:
- beautifulsoup4
- requests
- openpyxl
Para esto en el directorio que contendrá nuestro codigo abrimos una terminal y ejecutamos los siguientes comandos.
Los comandos los estoy realizando en una terminal de powershell
python -m venv venv
.\venv\Scripts\activate
pip install requests beautifulsoup4 openpyxl
Fuente de datos
Para el ejemplo estoy utilizando los datos de una aplicación que cree para que puedan descargar y hackear 😉.
Cómo correr la aplicación se encuentra en el readme, les dejo el link app_for_web_scrapping
Codigo
Procesamiento de la página
La página de la cual vamos a obtener los datos contiene una tabla como esta:
Fecha | Venta | Compra |
---|---|---|
2023-01-02 | 346.0 | 342.0 |
2023-01-03 | 354.0 | 350.0 |
2023-01-04 | 354.0 | 350.0 |
2023-01-05 | 353.0 | 349.0 |
Primero obtengamos los datos de la página y procesamos los datos obtenidos con beautiful soup
import requests
from bs4 import BeautifulSoup
url = "http://localhost:3001/dollar-history"
page = requests.get(url)
soup = BeautifulSoup(str(page.content), 'html.parser')
table_data = []
for line in soup.find_all('tr'):
header = line.find_all('th')
data = line.find_all('td')
if len(header) != 0:
table_data.append([data.get_text() for data in header])
if len(data) != 0:
table_data.append([data.get_text().replace('$ ', '') for data in data])
url: esta variable alberga el string con la dirección de la página en la que se encuentran los datos.
page: contiene el objeto obtenido del request hecho con la librería requests.
soup: contiene el objeto de procesar el contenido BeautifulSoup requiere dos parámetros, el contenido de la página y el procesador a utilizar en este caso html.
table_data: va a contener una lista con cada linea de la tabla.
Si revisamos la página con el inspector nos encontramos con una tabla y la misma contiene para cada línea el tag tr, dentro de estos para el header de la tabla se utiliza th y para los datos td
utilizando el método find_all(“tr”) obtenemos una lista con todas las lineas de la tabla.
luego recorremos con un for las lineas y en la misma buscamos si contiene el tag th o td para poder procesar el contenido del tag obtenido utilizando el metodo get_text() y agregamos la lista con el contenido de la tabla a table_data.
Con esto terminamos el procesamiento de la página y pasamos a trabajar los datos obtenidos.
Procesamiento de los datos
En el procesamiento de datos lo que se incluye en todas las solicitudes es grabar los mismos en algún tipo de archivo.
Las solicitudes en general son archivo csv, excel o json
Veamos cómo resolvemos esto con Python utilizando los datos que tenemos en table_data
CSV
# Escribir en un archivo csv
with open("export.csv", "w") as csv_file:
# Formato en un string
table_data_to_print = ""
for line in table_data:
for i in range(3):
if i == 2:
table_data_to_print += f"{line[i]}\n"
else:
table_data_to_print += f"{line[i]},"
csv_file.write(table_data_to_print)
Lo mas sencillos es recorrer la lista table_data luego recorremos cada una de las listas que se encuentran en table_data y agregamos los datos como un string único en la variable table_data_to_print y al finalizar grabamos el archivo.
Si abrimos el archivo tendremos algo como lo siguiente:
Fecha,Venta,Compra
2023-01-02,346.0,342.0
2023-01-03,354.0,350.0
2023-01-04,354.0,350.0
JSON
Para grabar archivos json vamos a necesitar utilizar la librería json
# Escribir en un archivo json
import json
json_data = []
headers_for_json = []
for line in soup.find_all('tr'):
headers = line.find_all('th')
data = line.find_all('td')
if len(headers) != 0:
for header in headers:
headers_for_json.append(header.get_text())
if len(data) >= 1:
obj = {}
for i in range(3):
obj[headers_for_json[i]] = data[i].get_text().replace('$ ', '')
json_data.append(obj)
json_object = json.dumps(json_data, indent=4)
with open("export.json", "w") as json_file:
json_file.write(json_object)
En este caso luego de importar la librería json tendremos que procesar de otra manera los datos obtenidos de la página como podemos ver se obtuvieron los datos lo que se cambia es que se agregan a la lista diccionarios en vez de listas.
Con json.dumps() se procesa la lista con los diccionarios y se crea la lista con los distintos objetos correspondientes al formato json y por últimos los grabamos en un archivo json
Si abrimos el archivo veremos algo como lo siguiente:
[
{
"Fecha": "2023-01-02",
"Venta": "346.0",
"Compra": "342.0"
},
{
"Fecha": "2023-01-03",
"Venta": "354.0",
"Compra": "350.0"
}
]
Excel
Cuando utilizamos excel tenemos que acudir al uso de ciertas librerías, una opción seria instalar pandas que incluye varias librerías entre ellas la que utilizo en este ejemplo openpyxl
from openpyxl import Workbook
import openpyxl
wb = Workbook()
ws = wb.active
for line_data in table_data:
# Sabiendo los datos que se encuentran en la tabla podemos guardar los datos con el formato correcto
if line_data[0] == "Fecha":
ws.append(line_data)
else:
ws.append([ line_data[0], float(line_data[1]), float(line_data[2].replace('$ ','')) ])
wb.save("export.xlsx")
En este caso vemos cómo se procesan los datos que se encuentran en table_data de la misma forma y se van agregando los datos al sheet y por último son grabados en el excel
Conclusión
Vimos un breve procesamiento de los datos obtenidos de una página y como grabar los mismos en tres formatos distintos.
Recuerden revisar los distintos tags con el inspeccionador del explorador.