用BeautifulSoup加载巨大的xml文件



我正试图从stackoverflow数据转储中提取post。这些文件由大型.xml文件组成,尤其是90GB的文件Posts.xml

不幸的是,下面的行使用了高达400GB的RAM,然后使用量突然减少到200GB,但这个过程似乎挂起了,再也回不来了。

with open("Posts.xml", "r") as f:
posts = BeautifulSoup(f, features="html.parser")  # hangs
for x in posts.findAll("row"):
if post["posttypeid"] == "1":  # if it's a question
print(x["body"])

我尝试了不同的解析器,比如lxml,但这似乎没有帮助。由于我在这之后所做的只是在posts.findAll("row")上枚举以解析每一行的内容,我想知道这是否是一种在不将整个文件加载到内存中的情况下实现这一点的方法。

您可以使用SAX解析器来实现这一点,如下所示:

from xml import sax
from xml.sax.handler import ContentHandler
class PostDescriber(ContentHandler):
def startElement(self, name, attrs):
if name == 'row' and attrs.get('PostTypeId') == '1':
print(attrs.get('Body'))
sax.parse('Posts.xml', PostDescriber())

SAX解析器是一个流式解析器;它将调用处理程序,描述在解析文件时看到的内容(如元素的开头和结尾(。由于它不必记住文件的结构,因此不需要占用大量内存。

如果你想对单个问题体做一些更有趣的事情,而不仅仅是打印它们,那么这些问题体足够小,你可以依次将每个问题体传递给BeautifulSoup。

xml.sax包是Python标准库的一部分;文档中对其进行了描述,如果需要,您可以在ContentHandler上覆盖更多方法。对于来自不可信来源的XML文档,文档建议使用defosedxml.sax包。

最新更新