解析多个大型XML文件并写入CSV

2024-04-27 05:23:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我有大约1000个XML文件,每个文件大小为250MB。我需要从中提取一些数据并写入CSV。不能有任何重复条目。

我有一个4GB内存和AMD A8处理器的系统。你知道吗

我已经通过了一些以前的职位,但他们似乎没有回答我的问题。你知道吗

我已经用Python编写了代码,并在示例XML上进行了测试,效果很好。你知道吗

但是,当我在所有文件上使用它时,速度非常慢(每个文件都差不多15分钟),不得不中途终止进程。你知道吗

什么是加速这一进程的最佳解决方案?你知道吗

这是密码

path='data/*.xml'
t=[]
for fname in glob.glob(path):
    print('Parsing ',fname)
    tree=ET.parse(fname)
    root=tree.getroot()
    x=root.findall('//Article/AuthorList//Author')
    for child in x:
        try:
            lastName=child.find('LastName').text
        except AttributeError:
            lastName=''
        try:
            foreName=child.find('ForeName').text
        except AttributeError:
            foreName=''
        t.append((lastName,foreName))
    print('Parsed ',fname)

t=set(t)

我想要最快的方法来获取条目而不需要任何重复的值。 (也许存储在某个DB中而不是变量t中,那么存储在DB中的每个条目是否会因为更多的空闲RAM而加快速度?-无论是什么方法,我都需要方向)


Tags: 文件pathinchildtreefor进程条目
1条回答
网友
1楼 · 发布于 2024-04-27 05:23:47

不要将结果写入Python列表,而是创建一个带有UNIQUE约束的数据库表,并将所有结果写入该表。完成所有写入操作后,将DB表作为csv转储。你知道吗

如果您不想在写入DB时有任何附加的依赖项,我建议您使用sqlite3,因为在最近的Python安装中它是现成的。你知道吗

以下是一些代码:

import sqlite3
conn = sqlite3.connect('large_xml.db')  # db will be created
cur = conn.cursor()
crt = "CREATE TABLE foo(fname VARCHAR(20), lname VARCHAR(20), UNIQUE(fname, lname))"
cur.execute(crt)
conn.commit()

path='data/*.xml'
for fname in glob.glob(path):
    print('Parsing ',fname)
    tree=ET.parse(fname)
    root=tree.getroot()
    x=root.findall('//Article/AuthorList//Author')
    count = 0
    for child in x:
        try:
            lastName=child.find('LastName').text
        except AttributeError:
            lastName=''
        try:
            foreName=child.find('ForeName').text
        except AttributeError:
            foreName=''
        cur.execute("INSERT OR IGNORE INTO foo(fname, lname) VALUES(?, ?)", (foreName, lastName))
        count += 1
        if count > 3000:  # commit every 3000 entries, you can tune this
            count = 0
            conn.commit()

    print('Parsed ',fname)

填充数据库后,将其转储到csv,如下所示:

sqlite3 -header -csv large_xml.db "select * from foo;" > dump.csv

另外,尝试更快的解析方法。 此外,如果.text属性在大多数情况下可用, 以下可能比异常处理更快:

lastName = getattr(child.find('LastName'), 'text', '')

相关问题 更多 >