如何使用 lxml Python(来自 .XML-files)有效地解析特定行?
How to parse efficiently specific lines with lxml Python (from .XML-files)?
我已经编写了一个可以遍历 XML.file 中特定行的代码,但我认为由于效率低下,这不是很好的编码。我的示例 .XML 如下所示:
<data>0.0, 100.0</data>
<data>1.0, 101.0</data>
<data>2.0, 102.0</data>
<data>3.0, 103.0</data>
<data>4.0, 104.0</data>
<data>5.0, 105.0</data>
<data>6.0, 106.0</data>
<data>7.0, 107.0</data>
<data>8.0, 108.0</data>
<data>9.0, 109.0</data>
<data>10.0, 110.0</data>
实际上,我有成千上万的数据行,我只需要其中的一些(基本上,我只知道我想要的行 - 没有别的)。我想仅从特定行有效地解析和获取数据。为此(但效率不高),我可以使用 nested nested for 循环,但我敢打赌这不是好方法。但是,我还没有想出任何其他方法。假设我想解析并获取第 4 行到第 8 行的数据:
import lxml.etree as ET
a = list(range(5, 10, 1)) # lists row numbers I want to parse and get data (lists rows 4, 5, 6, 7, 8)
tree = ET.parse('x.xml')
data = [] # List results
for x in a: # loops data set
for y in x:
for z in tree.xpath('//data[{}]'.format(y)): #Uses xpath to find one by one data based on row number
datat = z.text
data.append(datat) # List results in each iteration
print(data)
则输出仅包括
4.0, 104.0
5.0, 105.0
6.0, 106.0
7.0, 107.0
8.0, 108.0
我已经考虑过是否应该使用 iterparse() 方法或其他方法。然而,这个 Liza Daly's parsing method 表明 Xpath 是一个很好的方法,但我想我应该重新考虑我的代码。太多的 for 循环似乎效率低下。有没有人有任何建议或提示(或进一步阅读的链接)如何改进此代码?
我不确定它是否更有效率,但你当然可以简化你的代码:
dat = [your xml above]
import lxml.html #needed to do this to be able to parse from string, not file
tree = lxml.html.fromstring(dat)
简化代码:
data = []
for i in range(5, 10, 1): #since xpath counts from 1, while range counts from zero
for z in tree.xpath(f'//data[{i}]'):
data.append(z.text)
检查它是否有效:
for item in data:
print(item)
输出:
4.0, 104.0
5.0, 105.0
6.0, 106.0
7.0, 107.0
8.0, 108.0
我做了一些测试。我的原始文件包含数万行,我只需要从 400 行中获取数据,所以我在测试中使用了它。问题中给出的示例太简单,无法找到任何差异。
上面提到的简化方法实际上更正了我的代码,因为它有错误。更正和简化的代码(答案)的求解时间为 3.0-3.5 seconds
然而,我发现了另一种方法,它只包含一个循环:
data = []
for z in tree.xpath('//data[position()>=4 and position()<=8]'):
data.append(z.text)
它的求解时间只有0.29 seconds
。
我已经编写了一个可以遍历 XML.file 中特定行的代码,但我认为由于效率低下,这不是很好的编码。我的示例 .XML 如下所示:
<data>0.0, 100.0</data>
<data>1.0, 101.0</data>
<data>2.0, 102.0</data>
<data>3.0, 103.0</data>
<data>4.0, 104.0</data>
<data>5.0, 105.0</data>
<data>6.0, 106.0</data>
<data>7.0, 107.0</data>
<data>8.0, 108.0</data>
<data>9.0, 109.0</data>
<data>10.0, 110.0</data>
实际上,我有成千上万的数据行,我只需要其中的一些(基本上,我只知道我想要的行 - 没有别的)。我想仅从特定行有效地解析和获取数据。为此(但效率不高),我可以使用 nested nested for 循环,但我敢打赌这不是好方法。但是,我还没有想出任何其他方法。假设我想解析并获取第 4 行到第 8 行的数据:
import lxml.etree as ET
a = list(range(5, 10, 1)) # lists row numbers I want to parse and get data (lists rows 4, 5, 6, 7, 8)
tree = ET.parse('x.xml')
data = [] # List results
for x in a: # loops data set
for y in x:
for z in tree.xpath('//data[{}]'.format(y)): #Uses xpath to find one by one data based on row number
datat = z.text
data.append(datat) # List results in each iteration
print(data)
则输出仅包括
4.0, 104.0
5.0, 105.0
6.0, 106.0
7.0, 107.0
8.0, 108.0
我已经考虑过是否应该使用 iterparse() 方法或其他方法。然而,这个 Liza Daly's parsing method 表明 Xpath 是一个很好的方法,但我想我应该重新考虑我的代码。太多的 for 循环似乎效率低下。有没有人有任何建议或提示(或进一步阅读的链接)如何改进此代码?
我不确定它是否更有效率,但你当然可以简化你的代码:
dat = [your xml above]
import lxml.html #needed to do this to be able to parse from string, not file
tree = lxml.html.fromstring(dat)
简化代码:
data = []
for i in range(5, 10, 1): #since xpath counts from 1, while range counts from zero
for z in tree.xpath(f'//data[{i}]'):
data.append(z.text)
检查它是否有效:
for item in data:
print(item)
输出:
4.0, 104.0
5.0, 105.0
6.0, 106.0
7.0, 107.0
8.0, 108.0
我做了一些测试。我的原始文件包含数万行,我只需要从 400 行中获取数据,所以我在测试中使用了它。问题中给出的示例太简单,无法找到任何差异。
上面提到的简化方法实际上更正了我的代码,因为它有错误。更正和简化的代码(答案)的求解时间为 3.0-3.5 seconds
然而,我发现了另一种方法,它只包含一个循环:
data = []
for z in tree.xpath('//data[position()>=4 and position()<=8]'):
data.append(z.text)
它的求解时间只有0.29 seconds
。