sábado, 25 de febrero de 2023

Web Scraping

 ¿Que es el Web Scraping?

Es usar, en este caso, Python para extraer contenido  y datos de un sitio web. Para poder usarlo es necesario tener unos conocimientos mínimos de como se estructura el lenguaje HTML. Este se basa en etiquetas. Y precisamente esas etiquetas son las que vamos a utilizar para extraer esos datos. 

Vamos a verlo con un ejemplo.  Supongamos que nos interesa extraer el valor liquidativo de un fondo de inversión. Ese valor liquidativo se publica por ejemplo en la siguiente página web.


https://www.quefondos.com/es/fondos/ficha/index.html?isin=ES0164853014


pagina web donde se recoge el valor del fondo

Para poder extraer el valor liquidativo tenemos que instalar las librerías - BeautifulSoup - y - Request -. 

La librería BeautifulSoup nos sirve para extraer información de contenido en formato HTML o XML.

La librería Requests se utiliza en Python para hacer peticiones HTTP.

Usaremos también la librería webbrowser que ya está instalada por defecto en la biblioteca estándar de Python y que usaremos al final del programa para abrir el navegador y ver la página web de donde hemos extraído los datos. Si no tienes instaladas las librerías lo puedes hacer con:

$ pip install beautifulsoup4
$ pip install requests

 El programa empezará importando las librerías y estableciendo en una variable la página web desde donde vamos a descargar los datos.

main.py

#!/usr/bin/env python3

# Si no los tenemos, instalamos BeautifulSoup y requests
# pip install beautifulsoup4
# pip install requests

from bs4 import BeautifulSoup
import requests
import webbrowser # esta instalado por defecto, nos lleva a una pagina web desde python.

URL = "https://www.quefondos.com/es/fondos/ficha/index.html?isin=ES0164853014"

Vamos a utilizar requests para obtener un objeto donde se encuentre la página que queremos con todos sus elementos.

...
URL = "https://www.quefondos.com/es/fondos/ficha/index.html?isin=ES0164853014"
page = requests.get(URL)

Si ejecutáramos este programa y el servidor nos proporcionase la página de forma correcta, obtendríamos la siguiente respuesta.

<Response [200]>

Sin embargo lo que a nosotros nos interesa es el contenido de esa página, lo que conseguiremos usando page.content, y luego extraeremos el código HTML para poder buscar el dato que queremos con el argumento "html.parser".

...
URL = "https://www.quefondos.com/es/fondos/ficha/index.html?isin=ES0164853014"
page = requests.get(URL)
# Lo que nos interesa de la pagina es el contenido por lo que usamos page.content
# y luego que lo pase en formato html
soup = BeautifulSoup(page.content, 'html.parser')

Si imprimimos esta variable "soup" obtendremos el código HTML de la página.

Código HTML de la página. "soup" 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html lang="es-ES">
<head>
<title>CAIXABANK SELECCION TENDENCIAS, FI PLUS (ES0164853014) · CAIXABANK ASSET MGMT</title>
<meta content="Fondo de inversión, Ficha, Informe, CAIXABANK SELECCION TENDENCIAS, FI PLUS, ISIN, ES0164853014, Gestora, CAIXABANK ASSET MGMT, Política de inversión, Valor liquidativo, Rentabilidad, Ranking, Riesgo, Rating VDOS, Comisiones, Gráfico, Evolución, Histórico" name="keywords"/>
<meta content="Consulta el informe de CAIXABANK SELECCION TENDENCIAS, FI PLUS (ISIN:ES0164853014). Gestionado por
CAIXABANK ASSET MGMT. Categoría VDOS: MIXTO FLEXIBLE" name="description"/>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<meta content="no-cache" http-equiv="cache-control">
<meta content="no-cache" http-equiv="pragma">
<meta content="index, follow" name="robots">
...
<div class="w100">
<h4 id="bodytitle_h3_3">Última valoración</h4>
<p>
<span class="floatleft">Valor liquidativo: </span><span class="floatright">14,677700 EUR</span>
</p>
<p>
<span class="floatleft">Patrimonio (miles de euros):</span><span class="floatright">1.338.861,29</span>
</p>
<p>
<span class="floatleft">Fecha: </span><span class="floatright">16/02/2023</span>
</p>
</div>
...


Ahora viene la parte manual del tema y lo más importante. Lo que necesitamos es encontrar dentro de que etiquetas está el valor que queremos localizar. Dentro de todo el código HTML de la página el valor liquidativo está dentro de la etiqueta <div class="w100">. Sin embargo al buscar en la página por esta etiqueta van a aparecer muchos elementos, más de los que nos gustaría, pero por lo menos ya hemos hecho una primera acotación.

Aquí os muestro el código que queremos buscar dentro de la página. Para analizar una página web una buena herramienta que se puede utilizar, es dentro del propio navegador buscar en herramientas, "herramientas para desarrolladores". Eso nos facilitará ver el código de la parte que nos interesa capturar. En nuestro caso es el siguiente:

<div class="w100">
<h4 id="bodytitle_h3_3">Última valoración</h4>
<p>
<span class="floatleft">Valor liquidativo: </span><span class="floatright">14,574500 EUR</span>
</p>
<p>
<span class="floatleft">Patrimonio (miles de euros):</span><span class="floatright">1.328.576,22</span>
</p>
<p>
<span class="floatleft">Fecha: </span><span class="floatright">19/02/2023</span>
</p>
<p>
<span class="floatleft">1 día: </span><span class="floatright"><span class="igual">0,00%</span></span>
</p>
</div>

 Para ello usaremos:

result = soup.find_all('div', class_="w100")

En la variable result se almacenará en forma de lista cada una de las etiquetas <div> que a la vez contengan la clase con el nombre "w100". Una de ellas contendrá el valor liquidativo que estamos buscando. Pero como en el código hay varias de ellas tenemos que buscar algo que diferencie la que nosotros buscamos del resto. En este caso, dentro de la etiqueta <div class="w100"> la que contiene el valor liquidativo es la que dentro tiene esta etiqueta <h4 id="body_title_h3_3>. Lo que haremos será iterar sobre la lista result buscando con i.find() aquella que contenga esta ultima etiqueta. Cuando la encontremos, usaremos el mismo método para localizar la etiqueta que contiene el valor liquidativo. El código completo de la aplicación sería el siguiente:

main.py

#!/usr/bin/env python3

# Si no los tenemos, instalamos BeautifulSoup y requests
# pip install beautifulsoup4
# pip install requests

from bs4 import BeautifulSoup
import requests
import sys
import webbrowser  # esta instalado por defecto, nos lleva a una pagina web desde python.

URL = "https://www.quefondos.com/es/fondos/ficha/index.html?isin=ES0164853014"
page = requests.get(URL)
# Lo que nos interesa de la pagina es el contenido por lo que usamos page.content
# y luego que lo pase en formato html
soup = BeautifulSoup(page.content, 'html.parser')
# Para la busqueda se pasa la etiqueta html en la que esta contenido el dato
# result = soup.find_all('span', class_="floatright")
result = soup.find_all('div', class_="w100")

valores = {}
for i in result:
    # getText() - elimina todas las etiquetas html y nos deja solo el contenido de texto.
    # find() - busca la primera conformidad con el parámetro buscado.
    # print(i.getText())
    key = i.find('h4', id="bodytitle_h3_3")
    if key is not None:
        titulo = i.find('h4', id="bodytitle_h3_3")
        valor = i.find('span', class_='floatright')
        print(titulo)
        print(valor)
        print(f"{titulo.getText()}: {valor.getText()}")
    print("------------------------------------------------------")

# Nos muestra la página web que le pasemos la url.
webbrowser.open(URL)
Finalmente, la salida que buscamos sería la siguiente:

------------------------------------------------------
<h4 id="bodytitle_h3_3">Última valoración</h4>
<span class="floatright">14,574500 EUR</span>
Última valoración: 14,574500 EUR
------------------------------------------------------
Puedes encontrar el código completo del programa en el siguiente enlace.


No hay comentarios:

Publicar un comentario