使用“pythons-etree.iterparse()”解析大型xml文件不正常。代码中有逻辑错误吗?
我想解析一个巨大的xml文件。这个巨大文件中的记录看起来确实像这样。一般来说,文件是这样的使用“pythons-etree.iterparse()”解析大型xml文件不正常。代码中有逻辑错误吗?,python,xml,lxml,elementtree,iterparse,Python,Xml,Lxml,Elementtree,Iterparse,我想解析一个巨大的xml文件。这个巨大文件中的记录看起来确实像这样。一般来说,文件是这样的 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE dblp SYSTEM "dblp.dtd"> <dblp> record_1 ... record_n </dblp> 编辑: 当我写这个函数时,我完全被误导了。我犯了一个巨大的错误,我忽略了,当我试图跳过一些不想要的录音时
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE dblp SYSTEM "dblp.dtd">
<dblp>
record_1
...
record_n
</dblp>
编辑:
当我写这个函数时,我完全被误导了。我犯了一个巨大的错误,我忽略了,当我试图跳过一些不想要的录音时,却被一些想要的录音弄得一团糟。在文件中的某一点上,我连续跳过了将近一百万条记录,下面的通缉记录被炸毁了
在约翰和保罗的帮助下,我设法重写了我的代码。它现在正在解析,我们希望能把它做好。如果一些意外的错误仍然没有解决,我会向你汇报。另外,谢谢大家的帮助!我真的很感激
def fast_iter2(context, cursor):
elements = set([
'article', 'inproceedings', 'proceedings', 'book', 'incollection',
'phdthesis', "mastersthesis", "www"
])
childElements = set(["title", "booktitle", "year", "journal", "ee"])
paper = {} # represents a paper with all its tags.
authors = [] # a list of authors who have written the paper "together".
paperCounter = 0
for event, element in context:
tag = element.tag
if tag in childElements:
if element.text:
paper[tag] = element.text
# print tag, paper[tag]
elif tag == "author":
if element.text:
authors.append(element.text)
# print "AUTHOR:", authors[-1]
elif tag in elements:
paper["element"] = tag
paper["mdate"] = element.get("mdate")
paper["dblpkey"] = element.get("key")
# print tag, element.get("mdate"), element.get("key"), event
if paper["element"] in ['phdthesis', "mastersthesis", "www"]:
pass
else:
populate_database(paper, authors, cursor)
paperCounter += 1
print paperCounter
paper = {}
authors = []
# if paperCounter == 100:
# break
element.clear()
while element.getprevious() is not None:
del element.getparent()[0]
del context
在检测元素中标记的开始和停止的代码块中添加print语句,以确保正确地检测到这些标记。我怀疑由于某种原因,您没有找到清除作者列表的代码 尝试注释此代码(或至少将其移动到“end”处理块):
Python应该在遍历XML时为您清除这些元素。“del上下文”也是多余的。让引用计数器为您完成这里的工作。请消除一个混淆源:您并没有说您显示的代码实际上在一个“count of things>2000”测试中出错。如果不是,那么问题在于数据库更新代码(您没有向我们展示) 如果这样做,则会绊倒: (1) 将限制从2000降低到合理值(对于
auth
约为20,对于mydict正好为7)
(2) 当跳闸发生时,打印报告(mydict);印刷品;打印repr(auth)
并将内容与文件进行比较分析
旁白:对于iterparse(),不能保证在“开始”事件发生时解析elem.text。为了节省一些运行时间,您应该仅在“结束”事件发生时访问elem.text。事实上,似乎根本没有理由想要“开始”活动。您还定义了一个列表标记
,但从不使用它。函数的开头可以写得更简洁:
def fast_iter(context, cursor):
mydict = {} # represents a paper with all its tags.
auth = [] # a list of authors who have written the paper "together".
counter = 0 # counts the papers
tagset1 = set(['article', 'inproceedings', 'proceedings', 'book', 'incollection'])
tagset2 = set(["title", "booktitle", "year", "journal"])
for event, elem in context:
tag = elem.tag
if tag in tagset2:
if elem.text:
mydict[tag] = elem.text
elif tag == "author":
if elem.text:
auth.append(elem.text)
elif tag in tagset1:
counter += 1
print counter
mydict["element"] = tag
mydict["mdate"] = elem.get("mdate")
mydict["dblpkey"] = elem.get("key")
#populate_database(mydict, auth, cursor)
mydict.clear() # Why not just do mydict = {} ??
auth = []
# etc etc
不要忘记修复对iterparse()的调用以删除事件arg
此外,我还可以合理地确定,elem.clear()只应在事件为“end”时执行,并且只需在tagset1中的
标记时执行。仔细阅读。在“开始”事件中进行清理很可能会损坏您的树。有专门的文档记录,除非您采取特定的操作来清理,否则iterparse()将构建整个树。阅读以下内容:@John-谢谢,我个人并不熟悉iterparse,但我有一种预感,在事件结束前清除元素会把事情搞砸。不过,我必须说,必须清理这些增量变量并不是我所期望的名称以“iter”开头的东西。谢谢你的建议。我修改了它们,更正了问题中的代码,并将其标记为“编辑”。这是一个很好的建议。未分析我的elem.text
字段,因为我正在分析“开始”事件。寻找“结束”事件解决了这个问题。
elem.clear()
while elem.getprevious() is not None:
del elem.getparent()[0]
def fast_iter(context, cursor):
mydict = {} # represents a paper with all its tags.
auth = [] # a list of authors who have written the paper "together".
counter = 0 # counts the papers
tagset1 = set(['article', 'inproceedings', 'proceedings', 'book', 'incollection'])
tagset2 = set(["title", "booktitle", "year", "journal"])
for event, elem in context:
tag = elem.tag
if tag in tagset2:
if elem.text:
mydict[tag] = elem.text
elif tag == "author":
if elem.text:
auth.append(elem.text)
elif tag in tagset1:
counter += 1
print counter
mydict["element"] = tag
mydict["mdate"] = elem.get("mdate")
mydict["dblpkey"] = elem.get("key")
#populate_database(mydict, auth, cursor)
mydict.clear() # Why not just do mydict = {} ??
auth = []
# etc etc