我需要搜索~10M小(5-10K)XML文档以获取两个标签的文本内容。标签并不总是出现在树中的相同位置,也不总是出现在文档中。
只是为了澄清,如果我有这样的文件:
<a>
<b>
<c>
hello
</c>
<d>
goodbye
</d>
</b>
<e>
<c>
howdy
</c>
<g>
nope
</g>
</e>
</a>
<d>
salutations
</d>
我需要从c和d标签中提取文本信息,我会得到
hello goodbye howdy salutations
我目前正在使用xml.etree.ElementTree.findall('.//c')
,但它的运行速度非常慢。有没有更快的方法来找到这些标签?我应该使用XML解析库吗?
我正在使用Python 2.7和xml.etree.ElementTree。
答案 0 :(得分:1)
在lxml docs(http://lxml.de/performance.html)
中找到了一些基准测试树遍历
XML处理的另一个重要领域是树遍历的迭代。如果您的算法可以从XML树的逐步遍历中受益,特别是如果感兴趣的元素很少或目标元素标记名称已知,则.iter()方法是一个不错的选择:
lxe: iter_all (--TR T1) 1.0529 msec/pass
cET: iter_all (--TR T1) 0.2635 msec/pass
lxe: iter_islice (--TR T2) 0.0110 msec/pass
cET: iter_islice (--TR T2) 0.0050 msec/pass
lxe: iter_tag (--TR T2) 0.0079 msec/pass
cET: iter_tag (--TR T2) 0.0112 msec/pass
lxe: iter_tag_all (--TR T2) 0.1822 msec/pass
cET: iter_tag_all (--TR T2) 0.5343 msec/pass
这直接转换为Element.findall()的相似时间:
lxe: findall (--TR T2) 1.7176 msec/pass
cET: findall (--TR T2) 0.9973 msec/pass
lxe: findall (--TR T3) 0.3967 msec/pass
cET: findall (--TR T3) 0.2525 msec/pass
lxe: findall_tag (--TR T2) 0.2258 msec/pass
cET: findall_tag (--TR T2) 0.5770 msec/pass
lxe: findall_tag (--TR T3) 0.1085 msec/pass
cET: findall_tag (--TR T3) 0.1919 msec/pass
请注意,除了原生树迭代器(element.iter())之外,所有三个库当前对.findall()使用相同的Python实现。通常,lxml对于迭代来说非常快,但是当找到许多元素并且需要实例化时,它会对cET失去作用。因此,您的搜索选择性越强,lxml的运行速度就越快。
答案 1 :(得分:1)
根据评论的声音,您有两个非常具体的标签。无需解析整个文件。
import re
pattern = re.compile(r'<[c|d][^>]*>(?P<text>[^<]*)</[c|d]>')
with open('filename', 'r') as f:
for txt in pattern.finditer(f.read()):
print(txt.group('text').strip())
使用已编译的正则表达式并避免完全解析xml解析器,您应该会看到显着的加速。