Calificación:
  • 0 voto(s) - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
Aporte Web scraping con python BeautifulSoup y MySql
#1
Saludos.

Vamos a recoger los datos que nos interesan de una página web y los vamos a meter en una base de datos MySql para su almacenamiento y posteriormente tratar esos datos como mas nos convenga.

Yo trabajo en entorno linux, pero bajo Windows o MAc debería funcionar igual.

Para poder realizar este trabajo necesitaremos tener instalado MySql en nuestro PC. Además, entre otras librerías tenemos que tener instalada la de BeautifulSoup y el conector a la base de datos MySql

Código:
sudo pip install beautifulsoup4

sudo pip install mysql-connector

En este ejemplo vamos a trabajar con la página de la Bolsa de Madrid, si la quieres ver PULSA AQUI, concretamente en la sección donde nos da la información de las cotizaciones de las empresas del Ibex 35. Esta información se actualiza cada 15 minutos, pero nosotros vamos a ejecutar nuestro script a la hora de cierre para saber como han cerrado las cotizaciones día por día.

Yo he creado una base de datos llamada "ibex35" con una tabla llamada "diario" y en esta tabla 9 campos, id, nombre, fecha, ultimo, diferencia, max, min, volumen y efectivo.

Voy a poner el script completo y luego comentaremos por bloques.

Código:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
from bs4 import BeautifulSoup
import requests
from functools import reduce
import os
import mysql.connector
import datetime
website_url = requests.get("http://www.bolsamadrid.es/esp/aspx/Mercados/Precios.aspx?indice=ESI100000000&punto=indice").text
soup = BeautifulSoup(website_url,'lxml')
soup = soup.find('table',{'id':'ctl00_Contenido_tblAcciones'})
rows = soup.findAll("tr")[1:]
headers = {}
thead = soup.findAll("th")
for i in range(len(thead)):
   headers[i] = thead[i].text.strip().lower()
data = []
for row in rows:
   cells = row.find_all("td")
   item = {}    
   for i in headers:
       item[headers[i]] = cells[i].text  
   data.append(item)
pepe = json.dumps (data, indent=4)
diccionario = [
("\\u00fa", "u"),
("\\u00ed", "i"),
("\\u00e1", "a"),
("\\u20ac", "€")  
]
salida = reduce(lambda a, kv: a.replace(*kv), diccionario, pepe)
data = json.loads(salida)
mydb = mysql.connector.connect(
 host="localhost",
 user="usuario",
 passwd="contraseña",
 database="ibex35"
)
mycursor = mydb.cursor()
for device in data:
  fecha = datetime.datetime.strptime(device["fecha"], '%d/%m/%Y')
  sql = "INSERT INTO diario (nombre, fecha, ultimo, diferencia, max, min, volumen, efectivo) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)"
  val = (device["nombre"], fecha, device["ult."].replace(".", "").replace(",", "."), device["% dif."].replace(".", "").replace(",", "."), device["max."].replace(".", "").replace(",", "."), device["min."].replace(".", "").replace(",", "."), device["volumen"].replace(".", "").replace(",", "."), device["efectivo (miles €)"].replace(".", "").replace(",", "."))
  mycursor.execute(sql, val)
  mydb.commit()
  print(mycursor.rowcount, "Datos de ",device["nombre"]," introducidos correctamente")
print ("Todos los datos han sido introducidos correctamente")



BLOQUE 1

Código:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
from bs4 import BeautifulSoup
import requests
from functools import reduce
import os
import mysql.connector
import datetime
website_url = requests.get("http://www.bolsamadrid.es/esp/aspx/Mercados/Precios.aspx?indice=ESI100000000&punto=indice").text
soup = BeautifulSoup(website_url,'lxml')
soup = soup.find('table',{'id':'ctl00_Contenido_tblAcciones'})

En este bloque cargamos todas las librerías necesarias, cargamos la página y metemos en una variable la tabla que nos interesa, concretamente la que tiene id = ctl00_Contenido_tblAcciones.



BLOQUE 2 

Código:
rows = soup.findAll("tr")[1:]
headers = {}
thead = soup.findAll("th")
for i in range(len(thead)):
   headers[i] = thead[i].text.strip().lower()
data = []
for row in rows:
   cells = row.find_all("td")
   item = {}    
   for i in headers:
       item[headers[i]] = cells[i].text  
   data.append(item)
pepe = json.dumps (data, indent=4)  

En este bloque con todos los datos almacenados de la tabla creamos un json con la estructura cabecera tabla / valor, eso por cada fila de la tabla.



BLOQUE 3 

Código:
diccionario = [
("\\u00fa", "u"),
("\\u00ed", "i"),
("\\u00e1", "a"),
("\\u20ac", "€")  
]
salida = reduce(lambda a, kv: a.replace(*kv), diccionario, pepe)
data = json.loads(salida)
mydb = mysql.connector.connect(
 host="localhost",
 user="usuario",
 passwd="contraseña",
 database="ibex35"
)
mycursor = mydb.cursor()
for device in data:
  fecha = datetime.datetime.strptime(device["fecha"], '%d/%m/%Y')
  sql = "INSERT INTO diario (nombre, fecha, ultimo, diferencia, max, min, volumen, efectivo) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)"
  val = (device["nombre"], fecha, device["ult."].replace(".", "").replace(",", "."), device["% dif."].replace(".", "").replace(",", "."), device["max."].replace(".", "").replace(",", "."), device["min."].replace(".", "").replace(",", "."), device["volumen"].replace(".", "").replace(",", "."), device["efectivo (miles €)"].replace(".", "").replace(",", "."))
  mycursor.execute(sql, val)
  mydb.commit()
  print(mycursor.rowcount, "Datos de ",device["nombre"]," introducidos correctamente")
print ("Todos los datos han sido introducidos correctamente")

En este bloque lo primero que hacemos, como la página web tiene acentos y python no es amigo de ellos, ha escrito símbolos raros en las palabras que tenían acentos, cambiamos esos símbolos por las sílabas pero sin los acentos.
Volvemos a cargar en json, conectamos con la base de datos y hacemos un bucle for para hacer insert por cada fila de la tabla.

Nótese que debemos de hacer varios "replace" pues la información de la página nos da los miles en puntos y los decimales con comas, cosa que no admite la base de datos mysql, por lo que quitamos los puntos y las comas las transformamos en puntos. También transformamos el campo fecha en tipo "date".

Bueno, ya está, espero que le sirva a alguien.

Saludos.
[Imagen: chuck.gif]
Responder



Salto de foro:


Usuarios navegando en este tema: 1 invitado(s)