【问题标题】:BeautifulSoup: How to get the nearest tagBeautifulSoup:如何获取最近的标签
【发布时间】:2014-08-16 18:02:10
【问题描述】:

我有一个包含以下数据的 xml 文件

<year>2013</year>
<youSaveSpend>2500</youSaveSpend>
<yourMpgVehicle>
<avgMpg>32.261695541</avgMpg>
<cityPercent>43</cityPercent>
<highwayPercent>57</highwayPercent>
</yourMpgVehicle>

<year>2013</year>
<youSaveSpend>3000</youSaveSpend>
<yourMpgVehicle>
<avgMpg>33.383275416</avgMpg>
<cityPercent>49</cityPercent>
<highwayPercent>51</highwayPercent>
</yourMpgVehicle>

<year>2012</year>
<youSaveSpend>2500</youSaveSpend>
<yourMpgVehicle>
<avgMpg>36.210640188</avgMpg>
<cityPercent>32</cityPercent>
<highwayPercent>68</highwayPercent>
</yourMpgVehicle>

我想使用 BeautifulSoup 返回仅 2013 年的 avgMpg 列表?我该怎么做?

我目前的努力是:

for item in soupedCarAvgMpgPage.findAll('year'):
    listOfYears.append(''.join(item.findAll(text=True)))

for item in soupedCarAvgMpgPage.findAll('avgmpg'):
    listOfAvgMpg.append(''.join(item.findAll(text=True)))

print listOfYears
print listOfAvgMpg;

dictionaryYearToAvgMpg = dict(zip(listOfYears, listOfAvgMpg));

但字典不接受重复:S

【问题讨论】:

  • 请包括您当前的努力,我们将帮助您解决它。但是,这不是代码编写服务。
  • 你在哪里卡住了?为什么你对使用xml的原生python库不感兴趣
  • 为什么不this
  • 首先,如果希望将标签与后续标签匹配以获取它们之间的关系,则此 XML 格式不严格。这些元素应该在另一个标签内。其次,你不能使用dict,对吧?只是迭代这些值?
  • 要扩展您的几乎解决方案,您实际上可以这样做:[avgMpg for year, avgMpg in zip(listOfYears, listOfAvgMpg) if year==2013] 以获得您想要的。

标签: python python-2.7 beautifulsoup


【解决方案1】:

由于我们知道元素会彼此靠近,我们可以通过搜索next_siblings 到达那里:

from bs4 import BeautifulSoup

with open('mpg.xml') as f:
    contents=f.read()

mpgs = BeautifulSoup(contents)

def find_nearest_vehicle(elem):
    for sibling in elem.next_siblings:
        if sibling.name == 'yourmpgvehicle':
            return sibling

def find_avg_mpg(elem):
    for child in elem.children:
        if child.name == 'avgmpg':
            return child

year_2013 = [year for year in mpgs.find_all('year')
             if year.string == '2013']

avgmpg = [find_avg_mpg(find_nearest_vehicle(elem)).string
          for elem in year_2013]

print(avgmpg)

当我在你的文件上运行它时,我得到:

$ python3 mpg.py
['32.261695541', '33.383275416']

【讨论】:

  • 你应该得到32.26133.383,对吧?
  • 要获取内容,可以使用.string而不是next_element
  • 我认为最好在.next_siblings 中搜索名为avgMpg 的标签,而不是硬编码over(elem, 4),因为空格可能会改变。
  • 是的,我也只是将其更改为进行搜索。我会像您一样指出,像这样解析 XML 并不是很理想。您应该将元素按其分组标签进行分组,而不是像@user1607549 那样在物理上彼此靠近。
  • 看起来不错。只是你真的不需要搜索来找到avgmpg,你可以直接搜索find_nearest_vehicle(elem).avgmpg
【解决方案2】:

你快到了,你可以把你的最后一行改成这样:

result = [avgMpg for year, avgMpg in zip(listOfYears, listOfAvgMpg) if year=='2013']

请注意,2013 是字符串,而不是整数。

或者,对于缩短的整体代码(我将年份转换为 ints 和 avgMpgs 转换为 floats):

from bs4 import BeautifulSoup as BS
soup = BS(string, 'lxml')
listOfYears = [int(el.string) for el in soup.find_all('year')]
listOfAvgMpg = [float(el.string) for el in soup.find_all('avgmpg')]
result = [avgMpg for year, avgMpg in zip(listOfYears, listOfAvgMpg) if year==2013]
print result

结果:

[32.261695541, 33.383275416]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 2018-08-28
    • 1970-01-01
    • 2015-10-22
    相关资源
    最近更新 更多