Biblioteca de Python para analizar documentos HTML y XML (incluyendo los que tienen un marcado incorrecto). Se utiliza para el Web scraping.
pip install beautifulsoup4
También es necesario instalar requests para poder descargar contenido web, añadir cabeceras, etc.
pip install requests
Pasos:
requests (indicando cabeceras si es necesario).find())
Si queremos usar la misma cabecera que la de nuestro navegador, podemos ir a la web http://www.xhaus.com/headers y anotar lo que ponga en User-Agent:
headers = { "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:85.0) Gecko/20100101 Firefox/85.0" }
import bs4 import requests # es el módulo que hará la descarga # Para las webs que no permiten scraping, le hacemos creer que # nos estamos conectando con un navegador headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36'} res = requests.get("https://www.amazon.es/dp/B078211KBB/", headers = headers) # Nos aseguramos de que no ha habido errores al descargar la web anterior res.raise_for_status() soup = bs4.BeautifulSoup(res.text, "html.parser") titulo = soup.find("span", attrs={"id": "productTitle"}).string.strip() try: # Precios normales precio = soup.find("span", attrs={'id':'priceblock_ourprice'}).string.strip() except AttributeError: # Precios de oferta precio = soup.find("span", attrs={'id':'priceblock_dealprice'}).string.strip() # Se crea un objeto 'BeautifulSoup' donde se podrán hacer búsquedas # utilizando selectores CSS, por ejemplo: #elementos = soup.select('html head title') print(titulo) print(precio) # Eliminamos el HTML quedándonos solo con el texto: #elementos[0].text # Quitamos también saltos de línea y espacios: #elementos[0].text.strip()
Otro similar:
#! /usr/bin/env python import requests from bs4 import BeautifulSoup import smtplib headers = { "User-agent": 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'} URL = 'https://www.amazon.es/Raspberry-PI-4B-8GB-RAM/dp/B0899VXM8F/ref=sr_1_6?__mk_es_ES=%C3%85M%C3%85%C5%BD%C3%95%C3%91&dchild=1&keywords=raspberry+pi&qid=1612905463&sr=8-6' def amazon(): page = requests.get(URL, headers=headers) soup = BeautifulSoup(page.content, 'html.parser') title = soup.find(id="productTitle").get_text() price = soup.find(id="priceblock_ourprice").get_text() sep = ',' con_price = price.split(sep, 1)[0] converted_price = int(con_price.replace('.', '')) # título y precio print(title.strip()) print(converted_price) amazon()
from bs4 import BeautifulSoup import requests url = "https://direccion.web" result = requests.get(url) # Contenido de la petición # print(result.text) doc = BeautifulSoup(result.text, "html.parser") # Mostrarlo bien sangrado # print(doc.prettify()) """ Buscar por un texto (y aprovechar el resultado para obtener el elemento padre) Queremos llegar a un precio que comienza por el signo "$" """ prices = doc.find_all(text="$") parent = prices[0].parent strong = parent.find("strong") print(strong.string)
find(): busca el primer elemento que encuentrefind_all(): busca todos los elementosPodemos buscar más de un elemento a la vez:
doc.find_all(["p", "div", "li"])
Podemos buscar un elemento que tenga cierto texto:
doc.find_all(["option"], text="Rojo")
Buscar atributos de cierto elemento, por ejemplo el atributo value de la etiqueta option:
doc.find_all(["option"], value="rojo")
Búsqueda por clases CSS:
tag = doc.find_all(class_="btn-item")
class es una palabra reservada de Python, así que el argumento para buscar por clases lleva un guion bajo, y así diferenciarlo.
Búsqueda por expresión regular:
import re # Buscar un signo de dólar y lo que venga después tags = doc.find_all(text=re.compile("\$.*"))
Limitar los resultados de búsqueda:
import re # Buscar un signo de dólar y lo que venga después tags = doc.find_all(text=re.compile("\$.*"), limit=1)
Búsqueda por proximidad en la estructura de árbol, por ejemplo, nodos hermanos, padre y descendientes:
from bs4 import BeautifulSoup import requests url = "https://coinmarketcap.com/" result = requests.get(url).text doc = BeautifulSoup(result, "html.parser") tbody = doc.tbody trs = tbody.contents print(trs[1].next_sibling) # Nodo padre: print(trs[0].parent) # Descendientes print(trs[0].descendants) #print(trs[0].children) #print(trs[0].contents)
Recorrer una tabla buscando precios:
from bs4 import BeautifulSoup import requests url = "https://coinmarketcap.com/" result = requests.get(url).text doc = BeautifulSoup(result, "html.parser") tbody = doc.tbody trs = tbody.contents prices = {} for tr in trs[:10]: for td in tr.contents: name, price = tr.contents[2:4] fixed_name = name.p.string fixed_price = price.a.string prices[fixed_name] = fixed_price print(prices)