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.

Transformando archivos XML a archivos CSV utilizando beautifulsoup.

Estoy tratando de analizar múltiples (eventualmente más de 1000) archivos xml para obtener tres información: persName, @ref y la /date. He logrado obtener todos los archivos y cuando uso print(), me da toda la información que quiero. Sin embargo, cuando intento escribir esa información en un archivo csv, solo se analiza el último archivo xml.

from bs4 import BeautifulSoup
import csv
import os
path = r'C:\programming1\my-app'

for filename in os.listdir(path):
    if filename.endswith(".xml"):
        fullpath = os.path.join(path, filename)

        f = csv.writer(open("test2.csv", "w"))
        f.writerow(["date", "Name", "pref"])

        soup = BeautifulSoup(open(fullpath, encoding="utf-8"), "lxml")
        # eliminando información innecesaria para aislar mejor //date
        for docs in soup.find_all('tei'):
            for pubstmt in soup.find_all("publicationStmt"): 
                pubstmt.decompose()
            for sourdesc in soup.find_all("sourceDesc"):
                sourdesc.decompose()
            for lists in soup.find_all("list"):
                lists.decompose()
            for heads in soup.find_all("head"):
                lists.decompose()
            # encontrando todas las fechas de los Protokolls bajo /title
            for dates in soup.find_all("date"):
                date = dates.get('when')

            # obteniendo todos los nombres de los archivos xml, excepto los que están en /list
            for Names in soup.find_all("persname"):
                nameonly = Names.contents
                nameref = Names.get("ref")
                f.writerow([date, nameonly, nameref])

Si coloco ‘writerow’ debajo de ‘for Names’, solo escribe toda la información del último archivo, y si coloco ‘writerow’ después de ‘for Names’, solo escribe la información de un nombre.

¿Alguien puede decirme qué estoy haciendo mal? He probado muchos bucles ‘for’ y ninguno parece funcionar.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El problema parece ser que el archivo CSV se abre y se escribe dentro del bucle for, lo que significa que cada iteración sobrescribe la escritura anterior. Para solucionar esto, mueve la apertura del archivo CSV y los encabezados de las columnas fuera del bucle for:

    from bs4 import BeautifulSoup
    import csv
    import os
    
    path = r'C:\programming1\my-app'
    
    # se movió esto fuera del bucle for
    f = csv.writer(open("test2.csv", "w"))
    f.writerow(["fecha", "Nombre", "ref"])
    
    for filename in os.listdir(path):
        if filename.endswith(".xml"):
            fullpath = os.path.join(path, filename)
    
            soup = BeautifulSoup (open(fullpath, encoding="utf-8"), "lxml")
            for docs in soup.find_all('tei'):
                for pubstmt in soup.find_all("publicationStmt"): 
                    pubstmt.decompose()
                for sourdesc in soup.find_all("sourceDesc"):
                    sourdesc.decompose()
                for lists in soup.find_all("list"):
                    lists.decompose()
                for heads in soup.find_all("head"):
                    lists.decompose()
                for dates in soup.find_all("date"):
                    date = dates.get('when')
                for Names in soup.find_all("persname"):
                    # se movió esto aquí para incluir todos los nombres
                    nameonly = Names.contents
                    nameref = Names.get("ref")
                    f.writerow([date, nameonly, nameref])
    

    Con este cambio, el archivo CSV se abrirá y escribirá una vez, y cada iteración sobre los archivos XML escribirá una nueva fila en él.

Comments are closed.