Extraiga tablas HTML en un marco de datos usando BeautifulSoup

Mehvish Ashiq 15 febrero 2024
Extraiga tablas HTML en un marco de datos usando BeautifulSoup

Python tiene varios paquetes para trabajar teniendo en cuenta los requisitos del proyecto; uno es BeautifulSoup, que se utiliza para analizar documentos HTML y XML.

Crea un árbol de análisis para las páginas analizadas que podemos usar para extraer información (datos) de HTML, lo cual es beneficioso para el web scraping. El tutorial de hoy enseña cómo raspar tablas HTML en un marco de datos usando el paquete BeautifulSoup.

Use BeautifulSoup para raspar tablas HTML en un marco de datos

No es necesario que siempre obtengamos los datos organizados y limpios cada vez.

A veces, necesitamos los datos que están disponibles en los sitios web. Para eso, debemos ser capaces de recogerlo.

Afortunadamente, el paquete BeautifulSoup de Python tiene la solución para nosotros. Aprendamos cómo podemos usar este paquete para raspar tablas en un marco de datos.

Primero, necesitamos instalar este paquete en nuestra máquina para poder importarlo a nuestros scripts de Python. Podemos usar el comando pip para instalar BeautifulSoup en el sistema operativo Windows.

pip install beautifulsoup

Puede visitar esta documentación para obtener más información. Sabemos que no estamos familiarizados con la estructura básica de la tabla HTML, que es importante saber mientras raspamos; entendamos que seguir junto con este tutorial.

estructura de la tabla html

En la tabla anterior, TH significa encabezado de tabla, TR significa fila de tabla y TD significa datos de tabla (lo llamamos celdas). Como podemos ver, cada fila de la tabla tiene varios datos de tabla, por lo que podemos iterar fácilmente sobre cada fila para extraer información.

Ahora, vamos a aprenderlo paso a paso.

  • Importar bibliotecas
    import requests
    import pandas as pd
    from bs4 import BeautifulSoup
    

    Primero, necesitamos importar todas estas bibliotecas, la biblioteca pandas para trabajar con marcos de datos, bs4 (sopa hermosa) para extraer datos y la biblioteca requests para realizar solicitudes HTTP usando Python.

  • Descargar contenido de la página web
    web_url = "https://pt.wikipedia.org/wiki/Lista_de_bairros_de_Manaus"
    data = requests.get(web_url).text
    # data
    # print(data)
    # print(type(data))
    

    Aquí, guardamos la URL requerida en la variable web_url y hacemos una solicitud HTTP utilizando el módulo requests.

    Usamos .get() del módulo requests para recuperar datos de la web_url especificada, mientras que .text significa que queremos recuperar datos como una cadena.

    Entonces, si imprimimos como print(type(data)), veremos que recuperamos el HTML de toda la página como una cadena. Puede jugar imprimiendo datos, print(datos) e print(tipo (datos)).

    Todos estos están en la valla de código anterior; puedes descomentarlas y practicar.

  • Crear objeto BeautifulSoup
    beautiful_soup = BeautifulSoup(data, "html.parser")
    # print(type(beautiful_soup.b))
    

    El objeto BeautifulSoup (beautiful_soup) representa todo el documento analizado. Entonces, podemos decir que es un documento completo que estamos tratando de raspar.

    En su mayoría, lo tratamos como un objeto Etiqueta, que también se puede verificar usando la declaración print(type(beautiful_soup.b)). Ahora, tenemos el HTML completo de la página requerida.

    El siguiente paso es averiguar la tabla que queremos, podríamos obtener información de la primera tabla, pero existe la posibilidad de varias tablas en la misma página web.

    Por lo tanto, es importante encontrar la tabla requerida que queremos raspar. ¿Cómo? Podemos hacerlo fácilmente inspeccionando el código fuente.

    Para eso, haga clic derecho en cualquier parte de la página web requerida y seleccione inspeccionar, presione Ctrl+Shift+C para seleccionar el elementos (resaltados en rojo en la siguiente captura de pantalla), también puede usar el cuadro de búsqueda para encontrar etiquetas específicas (resaltadas en verde en la siguiente captura de pantalla).

    inspeccionar elemento

    Tenemos tres mesas; como se muestra en la captura de pantalla anterior (vea este número en el cuadro de búsqueda, resaltado en verde), estamos usando la tabla resaltada con class="wikitable sortable jquery-tablesorter".

    El punto es, ¿por qué estamos usando el atributo clase para seleccionar la tabla? Es porque las tablas no tienen ningún título sino un atributo de clase.

  • Verificar tablas con sus clases
    print("Classes of Every table:")
    for table in beautiful_soup.find_all("table"):
        print(table.get("class"))
    

    Producción:

    Classes of Every table:
    ['box-Desatualizado', 'plainlinks', 'metadata', 'ambox', 'ambox-content']
    ['wikitable', 'sortable']
    ['nowraplinks', 'collapsible', 'collapsed', 'navbox-inner']
    

    Aquí, iteramos sobre todos los elementos <table> para encontrar sus clases obteniendo el atributo clase.

  • Buscar clases wikitable y sortable
    tables = beautiful_soup.find_all("table")
    table = beautiful_soup.find("table", class_="wikitable sortable")
    

    Primero, creamos una lista de todas las tablas y luego buscamos la tabla con las clases wikitable y sortable.

  • Cree un marco de datos y rellénelo
    df = pd.DataFrame(
        columns=["Neighborhood", "Zone", "Area", "Population", "Density", "Homes_count"]
    )
    
    mylist = []
    for table_row in table.tbody.find_all("tr"):
        table_columns = table_row.find_all("td")
    
        if table_columns != []:
            neighbor = table_columns[0].text.strip()
            zone = table_columns[1].text.strip()
            area = table_columns[2].span.contents[0].strip("&0.")
            population = table_columns[3].span.contents[0].strip("&0.")
            density = table_columns[4].span.contents[0].strip("&0.")
            home_count = table_columns[5].span.contents[0].strip("&0.")
    
            mylist.append([neighbor, zone, area, population, density, home_count])
    
    df = pd.DataFrame(
        mylist,
        columns=["Neighborhood", "Zone", "Area", "Population", "Density", "Homes_count"],
    )
    

    Aquí, definimos un marco de datos con las columnas Barrio, Zona, Área, Población, Densidad y Recuento de viviendas. Luego, iteramos sobre la tabla HTML para recuperar datos y completar el marco de datos que acabamos de definir.

  • Utilice df.head() para imprimir los primeros cinco documentos
    print(df.head())
    

    Producción:

       Neighborhood          Zone    Area Population   Density Homes_count
    0    Adrianópolis    Centro-Sul 248.45      10459   3560.88        3224
    1          Aleixo    Centro-Sul 618.34      24417    3340.4        6101
    2        Alvorada Centro-Oeste 553.18      76392 11681.73       18193
    3 Armando Mendes         Leste 307.65      33441   9194.86        7402
    4         Betânia           Sul   52.51       1294 20845.55        3119
    

Código fuente completo:

import requests
import pandas as pd
from bs4 import BeautifulSoup

web_url = "https://pt.wikipedia.org/wiki/Lista_de_bairros_de_Manaus"
data = requests.get(web_url).text

beautiful_soup = BeautifulSoup(data, "html.parser")

print("Classes of Every table:")
for table in beautiful_soup.find_all("table"):
    print(table.get("class"))


tables = beautiful_soup.find_all("table")
table = beautiful_soup.find("table", class_="wikitable sortable")

df = pd.DataFrame(
    columns=["Neighborhood", "Zone", "Area", "Population", "Density", "Homes_count"]
)

mylist = []
for table_row in table.tbody.find_all("tr"):
    table_columns = table_row.find_all("td")

    if table_columns != []:
        neighbor = table_columns[0].text.strip()
        zone = table_columns[1].text.strip()
        area = table_columns[2].span.contents[0].strip("&0.")
        population = table_columns[3].span.contents[0].strip("&0.")
        density = table_columns[4].span.contents[0].strip("&0.")
        home_count = table_columns[5].span.contents[0].strip("&0.")

        mylist.append([neighbor, zone, area, population, density, home_count])

df = pd.DataFrame(
    mylist,
    columns=["Neighborhood", "Zone", "Area", "Population", "Density", "Homes_count"],
)

print(df.head())

Producción :

Classes of Every table:
['box-Desatualizado', 'plainlinks', 'metadata', 'ambox', 'ambox-content']
['wikitable', 'sortable']
['nowraplinks', 'collapsible', 'collapsed', 'navbox-inner']
     Neighborhood          Zone    Area Population   Density Homes_count
0    Adrianópolis    Centro-Sul  248.45      10459   3560.88        3224
1          Aleixo    Centro-Sul  618.34      24417    3340.4        6101
2        Alvorada  Centro-Oeste  553.18      76392  11681.73       18193
3  Armando Mendes         Leste  307.65      33441   9194.86        7402
4         Betânia           Sul   52.51       1294  20845.55        3119
Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook