es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo raspar una tabla paginada con BeautifulSoup y almacenar los resultados en un archivo CSV?

Quiero extraer datos de https://www.airport-data.com/manuf/Reims.html y recorrer todos los registros para guardar los resultados en el archivo “AircraftListing.csv”.

El código se ejecuta sin errores, pero los resultados se almacenan incorrectamente y no se extraen todos los registros de la página web al archivo .csv.

¿Cómo puedo obtener todos los registros de aviación de Reims en AircraftListing.csv?

import requests
from bs4 import BeautifulSoup
import csv

root_url = "https://www.airport-data.com/manuf/Reims.html"
html = requests.get(root_url)
soup = BeautifulSoup(html.text, 'html.parser')

paging = soup.find("table",{"class":"table table-bordered table-condensed"}).find_all("td")

start_page = paging[1].text
last_page = paging[len(paging)-2].text

outfile = open('AircraftListing.csv','w', newline='')
writer = csv.writer(outfile)
writer.writerow(["Número de Cola", "Fabricante Modelo Año", "C/N","Motores", "Asientos", "Ubicación"])

pages = list(range(1,int(last_page)+1))
for page in pages:
    url = 'https://www.airport-data.com/manuf/Reims:%s.html' %(page)
    html = requests.get(url)
    soup = BeautifulSoup(html.text, 'html.parser')

    print ('https://www.airport-data.com/manuf/Reims:%s' %(page))

    product_name_list = soup.find("table",{"class":"table table-bordered table-condensed"}).find_all("td")

    # Cada fila tiene 6 elementos.
    # Recorre cada sexto elemento. (El primer elemento de cada fila)
    # Obtiene los demás elementos de la fila agregando el índice del primero.
    for i in range(int(len(product_name_list)/6)):
        Tail_Number = product_name_list[(i*6)].get_text('td')
        Year_Maker_Model = product_name_list[(i*6)+1].get_text('td')
        C_N = product_name_list[(i*6)+2].get_text('td')
        Engines = product_name_list[(i*6)+3].get_text('td')
        Seats = product_name_list[(i*6)+4].get_text('td')
        Location = product_name_list[(i*6)+5].get_text('td')

        writer.writerow([Tail_Number, Year_Maker_Model, C_N, Engines, Seats, Location])

outfile.close()
print ('Done')
Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El problema con el código podría ser debido al hecho de que la estructura de la tabla en la página web puede haber cambiado desde que se escribió el código. Se recomienda revisar y actualizar el código correspondientemente para que coincida con la última estructura de la tabla.

    Una posible solución podría ser agregar manejo de errores y registro al código para identificar cualquier problema que pueda ocurrir durante el proceso de scraping. Por ejemplo, agregar un bloque try-except para capturar cualquier excepción y escribir el mensaje de error en un archivo de registro para un análisis posterior:

    import requests
    from bs4 import BeautifulSoup
    import csv
    import logging
    
    # Configurar el registro
    logging.basicConfig(filename='scraper.log', level=logging.INFO)
    
    root_url = "https://www.airport-data.com/manuf/Reims.html"
    html = requests.get(root_url)
    soup = BeautifulSoup(html.text, 'html.parser')
    
    paging = soup.find("table",{"class":"table table-bordered table-condensed"}).find_all("td")
    
    start_page = paging[1].text
    last_page = paging[len(paging)-2].text
    
    
    outfile = open('DatosAeronaves.csv','w', newline='')
    writer = csv.writer(outfile)
    writer.writerow(["Número_Cola", "Año_Fabricante_Modelo", "C_N","Motores", "Asientos", "Ubicación"])
    
    pages = list(range(1,int(last_page)+1))
    for page in pages:
        url = 'https://www.airport-data.com/manuf/Reims:%s.html' %(page)
        html = requests.get(url)
        soup = BeautifulSoup(html.text, 'html.parser')
    
        logging.info('Extrayendo página: {}'.format(url))
        product_name_list = soup.find("table",{"class":"table table-bordered table-condensed"}).find_all("td")
    
        # Cada fila tiene 6 elementos.
        # Recorrer cada sexto elemento (el primer elemento de cada fila)
        # Obtener todos los otros elementos de la fila sumando al índice del primero.
        try:
            for i in range(int(len(product_name_list)/6)):
                Número_Cola = product_name_list[(i*6)].get_text('td')
                Año_Fabricante_Modelo = product_name_list[(i*6)+1].get_text('td')
                C_N = product_name_list[(i*6)+2].get_text('td')
                Motores = product_name_list[(i*6)+3].get_text('td')
                Asientos = product_name_list[(i*6)+4].get_text('td')
                Ubicación = product_name_list[(i*6)+5].get_text('td')
    
                writer.writerow([Número_Cola, Año_Fabricante_Modelo, C_N, Motores, Asientos, Ubicación])
        except Exception as e:
            logging.error('Ocurrió un error: {}'.format(e))
    
    outfile.close()
    print ('Hecho')
    

    Otra solución podría ser utilizar un método diferente para extraer los datos de la tabla, como usar la función pandas.read_html() para extraer fácilmente los datos de la tabla en un dataframe, y luego escribir el dataframe en un archivo csv:

    import requests
    import pandas as pd
    
    root_url = "https://www.airport-data.com/manuf/Reims.html"
    html = requests.get(root_url)
    df_list = pd.read_html(html.text)
    df = df_list[0] # seleccionar la primera tabla
    df.to_csv('DatosAeronaves.csv', index=False, header=["Número_Cola", "Año_Fabricante_Modelo", "C_N","Motores", "Asientos", "Ubicación"])
    

    Este método debería ser más confiable ya que se basa en el manejo incorporado de datos de tabla por parte de la biblioteca pandas.

Comments are closed.