Saltar al contenido

Extracción de datos del HTML con BeautifulSoup

En esta guía, aprenderemos a hacer un simple web scraping usando Python y BeautifulSoup .

Instalar las Bibliotecas Esenciales de Pitón

1pip3 install requests beautifulsoup4

Shell

Extracción de datos del HTML con BeautifulSoup
Extracción de datos del HTML con BeautifulSoup

Nota: Si utiliza Windows, utilice pip en lugar de pip3

Importación de las Bibliotecas Esenciales

Importar la biblioteca de «solicitudes» para obtener el contenido de la página y bs4 (Beautiful Soup) para analizar el contenido de la página HTML.

12de bs4 import BeautifulSoupimport requests

pitón

Recopilación y análisis de una página web

En el siguiente paso, haremos una petición GET a la url y crearemos un objeto de árbol de análisis (sopa) con la ayuda del analizador «lxml» incorporado de BeautifulSoup y Python.

123456789101112# importar las librerias de bs4 import BeautifulSoupimport requests# Hacer una solicitud GET para obtener el contenido HTML en brutotml_content = requests.get(url).text# Analizar el contenido htmloup = BeautifulSoup(html_content, "lxml")print(soup.prettify())# imprimir los datos analizados de html

pitón

Con nuestro objeto BeautifulSoup, es decir, sopa , podemos seguir adelante y recoger los datos de la tabla requerida.

Antes de ir al código real, juguemos primero con el objeto de la sopa e imprimamos alguna información básica de él:

Ejemplo 1:

Primero imprimamos el título de la página web.

1print(soup.title)

pitón

Dará un resultado como el siguiente:

1<título>;Lista de países por PIB (nominal) - Wikipedia</título>;

Para obtener el texto sin las etiquetas HTML, sólo usamos .text :

1print(soup.title.text)

pitón

Lo que resultará en:

1Lista de países por PIB (nominal) - Wikipedia

Ejemplo 2:

Ahora, consigamos todos los enlaces de la página junto con sus atributos, como href , title , y su Texto interno.

1234para el enlace en soup.find_all("a"):print("Inner Text": {}".format(link.text))print("Título: {}".format(link.get("title")))print("href: {}".format(link.get("href")))

pitón

Esto producirá todos los enlaces disponibles junto con sus atributos mencionados de la página.

Ahora, volvamos a la pista y encontremos nuestra mesa de objetivos.

Analizando la tabla exterior, podemos ver que tiene atributos especiales que incluyen la clase como wikitable y tiene dos tr etiquetas dentro del cuerpo.

Si se descoloca la etiqueta tr , se encontrará que la primera etiqueta tr es para los encabezados de las tres tablas y la siguiente tr es para los datos de las tablas de las tres tablas internas.

Primero, consigamos los tres encabezados de las mesas:

12345678910gdp_table = soup.find("table", attrs={"class": "wikitable"})gdp_table_data = gdp_table.tbody. find_all("tr")# contiene 2 filas# Obtener todos los encabezados de Listsheadings =[]for td en gdp_table_data[0].find_all("td"):# eliminar cualquier línea nueva y espacios extra de los encabezados izquierdo y derecho.append(td.b.text.replace($0027
$0027,$0027 $0027).strip())print(headings)

pitón

Esto dará una salida como:

1[$0027Por el Fondo Monetario Internacional (2018)$0027, $0027Por el Banco Mundial (2017)$0027, $0027Por las Naciones Unidas (2017)$0027]

Pasando a la segunda etiqueta tr de la tabla exterior, obtengamos el contenido de las tres tablas iterando sobre cada tabla y sus filas.

1234567891011121314151617181920212223data ={}para la tabla, encabezamiento inzip(gdp_table_data[1].find_all("table"), headings):# Obtener los encabezamientos de la tabla, es decir, Rango, País, PIB. t_headers =[]para th en table.find_all("th"):# eliminar cualquier línea nueva y espacios extra de la izquierda y la derecha t_headers.append(th.text.replace($0027
$0027,$0027 $0027).strip())# Obtener todas las filas de la tabla table_data =[]for tr en table.tbody. find_all("tr"):# encuentra todos los tr de t_body de la tabla t_row ={}# Cada fila de la tabla se almacena en forma de# t_row = {$0027Rank$0027: $0027$0027, $0027Country/Territory$0027: $0027$0027, $0027GDP(US$million)$0027: $0027$0027}# encuentra todos los td(3) de tr y los cierra con t_headerfor td, th inzip(tr. find_all("td"), t_headers): t_row[th]= td.text.replace($0027
$0027,$0027$0027).strip() table_data.append(t_row)# Poner los datos de la tabla con su encabezamiento. data[heading]= table_dataprint(data)

pitón

Escribiendo datos al CSV

Ahora que hemos creado nuestra estructura de datos, podemos exportarla a un archivo CSV con sólo iterar sobre ella.

1234567891011121314151617importar csvpara el tema, tabla en data.items():# Crear un archivo csv para cada tabla con w"{topic}. csv",$0027w$0027)as out_file:# Cada 3 tablas tiene los siguientes encabezados =["País/Territorio", "PIB(US$millones)", "Rango"]# == t_headers writer = csv.DictWriter(out_file, headers)# escribe el encabezado writer.writeheader()para la fila en la tabla:if fila: writer.writerow(row)

pitón

Poniéndolo todo junto

Unamos todos los fragmentos de código anteriores.

Nuestro código completo se ve así:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374# importando las bibliotecasdesde bs4 import BeautifulSoupimport requestsimport csv# Paso 1: Envío de una solicitud HTTP a una URLurl ="https://en. wikipedia.org/wiki/List_of_countries_by_GDP_(nominal) "# Hacer una solicitud GET para obtener el contenido HTML en brutotml_content = requests.get(url).text# Paso 2: Analizar el contenido htmloup = BeautifulSoup(html_content, "lxml")# print(soup.prettify()) # imprimir los datos analizados de html# Paso 3: Analizar la etiqueta HTML, donde vive su contenido# Crear un diccionario de datos para almacenar los datos.data ={}#Conseguir la tabla que tiene la clase wikitablegdp_table = soup.find("table", attrs={"class": "wikitable"})gdp_table_data = gdp_table. tbody.find_all("tr")# contiene 2 filas# Obtener todos los encabezados de Listsheadings =[]for td en gdp_table_data[0].find_all("td"):# eliminar cualquier línea nueva y espacios extra de los encabezados izquierdo y derecho.append(td.b.text.replace($0027
$0027,$0027 $0027).strip())# Obtener las 3 tablas contenidas en "gdp_table "para la tabla, encabezamiento inzip(gdp_table_data[1].find_all("table"), encabezamientos):# Obtener los encabezamientos de la tabla es decir, Rango, País, PIB. t_headers =[]para th en table.find_all("th"):# Eliminar cualquier línea nueva y espacios extra de la izquierda y la derecha t_headers.append(th.text.replace($0027
$0027,$0027 $0027).strip())# Obtener todas las filas de la tabla table_data =[]for tr en table.tbody. find_all("tr"):# encuentra todos los tr de t_body de la tabla t_row ={}# Cada fila de la tabla se almacena en forma de# t_row = {$0027Rank$0027: $0027$0027, $0027Country/Territory$0027: $0027$0027, $0027GDP(US$million)$0027: $0027$0027}# encuentra todos los td(3) de tr y los cierra con t_headerfor td, th inzip(tr. find_all("td"), t_headers): t_row[th]= td.text.replace($0027
$0027,$0027$0027).strip() table_data.append(t_row)# Poner los datos de la tabla con su encabezamiento. data[heading]= table_data# Paso 4: Exportar los datos a csv"""Para este ejemplo vamos a crear 3 csv separados para 3 tablas respectivamente"""para el tema, la tabla en data.items():# Crear el archivo csv para cada tablawithopen(f"{topic}. csv",$0027w$0027)como archivo_salida:# Cada 3 tablas tiene los siguientes encabezados =["País/Territorio", "PIB(US$millones)", "Rango"]# == t_headers writer = csv.DictWriter(archivo_salida, encabezados)# escribir el encabezado writer.writeheader()para la fila en la tabla:if fila: writer.writerow(fila)

pitón