Saya minta maaf untuk mengulangi pertanyaan ini, bagaimanapun, itu masih belum diselesaikan.

Ini bukan masalah yang sangat kompleks dan saya yakin ini cukup mudah, tapi saya tidak bisa melihat masalahnya.

Kode saya untuk parsing melalui file XML dibuka dan dibaca dalam format yang saya inginkan - pernyataan print di for-loop terakhir membuktikan hal ini.

Sebagai contoh ini menghasilkan ini:

Pegangan dukungan berputar D0584129 20090106 US

Engsel D0584130 20090106 US

Deadbolt turnpiece D0584131 20090106 US

Dan inilah tepatnya yang saya inginkan agar data saya ditulis ke dalam file CSV. Namun, ketika saya mencoba untuk benar-benar menulis ini sebagai baris ke dalam CSV itu sendiri, itu hanya mencetak salah satu baris terakhir dalam file XML dan dengan cara ini:

Paket senter, D0584138,20090106, AS

Berikut adalah seluruh kode saya karena mungkin membantu dalam memahami seluruh proses di mana area yang diminati adalah tempat untuk xml_string di dipisahkan_xml dimulai:

from bs4 import BeautifulSoup
import csv
import unicodecsv as csv

infile = "C:\\Users\\Grisha\\Documents\\Inventor\\2009_Data\\Jan\\ipg090106.xml"

# The first line of code defines a function "separated_xml" that will allow us to separate, read, and then finally parse the data of interest with

def separated_xml(infile):  # Defining the data reading function for each xml section - This breaks apart the xml from the start (root element <?xml...) to the next iteration of the root element 
    file = open(infile, "r")   # Used to open the xml file
    buffer = [file.readline()] # Used to read each line and placing inside vector
    
# The first for-loop is used to slice every section of the USPTO XML file to be read and parsed individually
# It is necessary because Python wishes to read only one instance of a root element but this element is found many times in each file which causes reading errors
    
    for line in file:       # Running for-loop for the opened file and searches for root elements
        if line.startswith("<?xml "):
            yield "".join(buffer)  # 1) Using "yield" allows to generate one instance per run of a root element and 2) .join takes the list (vector) "buffer" and connects an empty string to it
            buffer = []     # Creates a blank list to store the beginning of a new 'set' of data in beginning with the root element
        buffer.append(line) # Passes lines into list
    yield "".join(buffer)   # Outputs
    file.close()

# The second nested set of for-loops are used to parse the newly reformatted data into a new list

for xml_string in separated_xml(infile): # Calls the output of the separated and read file to parse the data
    soup = BeautifulSoup(xml_string, "lxml")     # BeautifulSoup parses the data strings where the XML is converted to Unicode
    pub_ref = soup.findAll("publication-reference") # Beginning parsing at every instance of a publication
    lst = []  # Creating empty list to append into
    

    with open('./output.csv', 'wb') as f:
        writer = csv.writer(f, dialect = 'excel')
    
        for info in pub_ref:  # Looping over all instances of publication
        
# The final loop finds every instance of invention name, patent number, date, and country to print and append into
        
            
                for inv_name, pat_num, date_num, country in zip(soup.findAll("invention-title"), soup.findAll("doc-number"), soup.findAll("date"), soup.findAll("country")):
                    print(inv_name.text, pat_num.text, date_num.text, country.text)
                    lst.append((inv_name.text, pat_num.text, date_num.text, country.text))                   
                    writer.writerow([inv_name.text, pat_num.text, date_num.text, country.text])

Saya juga mencoba menempatkan open dan writer di luar for-loop untuk memeriksa di mana masalah muncul tetapi tidak berhasil. Saya tahu bahwa file tersebut hanya menulis 1 baris pada satu waktu dan menimpa baris yang sama berulang-ulang (itulah sebabnya hanya 1 baris yang tersisa dalam file CSV), saya tidak dapat melihatnya.

Terima kasih banyak atas bantuannya sebelumnya.

1
HelloToEarth 10 Agustus 2017, 17:49

2 jawaban

Jawaban Terbaik

Saya percaya (toh teori kerja pertama) dasar masalah Anda adalah kenyataan bahwa pernyataan with open Anda termasuk dalam for loop Anda, dan menggunakan mode "wb" yang menimpa file jika sudah ada. Ini berarti setiap kali for loop Anda berjalan, ia menimpa apa pun yang ada sebelumnya, dan hanya menyisakan satu baris output setelah selesai.

Ada dua cara saya bisa melihat Anda menangani ini. Cara yang lebih benar adalah dengan memindahkan pernyataan buka file di luar for loop terluar. Saya tahu Anda menyebutkan bahwa Anda sudah mencoba ini, tetapi iblis ada dalam detailnya. Ini akan membuat kode Anda yang diperbarui terlihat seperti ini:

    with open('./output.csv', 'wb') as f:
      writer = csv.writer(f, dialect='excel')

      for xml_string in separated_xml(infile):
        soup = BeautifulSoup(xml_string, "lxml")
        pub_ref = soup.findAll("publication-reference")
        lst = []

        for info in pub_ref:

          for inv_name, pat_num, date_num, country in zip(soup.findAll("invention-title"), soup.findAll("doc-number"), soup.findAll("date"), soup.findAll("country")):
            print(inv_name.text, pat_num.text, date_num.text, country.text)
            lst.append((inv_name.text, pat_num.text, date_num.text, country.text))
            writer.writerow([inv_name.text, pat_num.text, date_num.text, country.text])

Cara hacky, tetapi lebih cepat dan lebih mudah adalah dengan hanya mengubah mode dalam panggilan terbuka Anda menjadi "ab" (tambahkan, biner) daripada "wb" (tulis biner, yang menimpa data yang ada). Ini jauh kurang efisien karena Anda masih membuka kembali file setiap kali melalui for loop, tetapi mungkin akan berhasil.

Saya harap ini membantu!

1
Justice Stiles 10 Agustus 2017, 15:42
with open('./output.csv', 'wb') as f:

Cukup diperlukan perubahan 'wb' -> 'ab' untuk tidak menimpa.

Tidak berfungsi pertama kali tetapi memindahkan fungsi pembukaan sebelum 2 loop terakhir memperbaikinya. Terima kasih kepada mereka yang membantu.

0
HelloToEarth 10 Agustus 2017, 16:05