如何在python 3.5中使用BeautifulSoup获取特定的xml标签?

时间:2018-01-18 05:09:20

标签: python xml beautifulsoup

这是我的芝加哥XML文件: 路线名称=“红色”>

<route name = "red">
<train>
<rn>830</rn>
<destSt>30089</destSt>
<destNm>95th/Dan Ryan</destNm>
<trDr>5</trDr>
<nextStaId>41000</nextStaId>
<nextStpId>30194</nextStpId>
<nextStaNm>Cermak-Chinatown</nextStaNm>
<prdt>20180117 22:41:16</prdt>
<arrT>20180117 22:42:16</arrT>
<isApp>1</isApp>
<isDly>0</isDly>
<flags/>
<lat>41.85532</lat>
<lon>-87.63133</lon>
<heading>176</heading>

<route name="blue">
<train>
<rn>134</rn>
<destSt>30077</destSt>
<destNm>Forest Park</destNm>
<trDr>5</trDr>
<nextStaId>40570</nextStaId>
<nextStpId>30112</nextStpId>
<nextStaNm>California</nextStaNm>
<prdt>20180117 22:40:47</prdt>
<arrT>20180117 22:42:47</arrT>
<isApp>0</isApp>
<isDly>0</isDly>
<flags/>
<lat>41.92528</lat>
<lon>-87.70238</lon>
<heading>122</heading>
</train>

我能够使用.find函数来提取列车的第一个列车编号和更多信息,但现在我想为'route = blue提取一列火车的标签(以及该特定火车的日期) '段落......我怎么能这样做?我遇到麻烦,因为每个标签都是一样的。

我提取第一个标签的当前代码如下:

train = XML.find('rn')
print(train)  #just a gist of the code

任何解决方案?我正在使用BeautifulSoup4

1 个答案:

答案 0 :(得分:0)

我不得不稍微更改你的xml因为它没有很好地形成,但假设xml看起来像这样:

<data>
  <route name="red">
    <train>
      <rn>830</rn>
      <destSt>30089</destSt>
      <destNm>95th/Dan Ryan</destNm>
      <trDr>5</trDr>
      <nextStaId>41000</nextStaId>
      <nextStpId>30194</nextStpId>
      <nextStaNm>Cermak-Chinatown</nextStaNm>
      <prdt>20180117 22:41:16</prdt>
      <arrT>20180117 22:42:16</arrT>
      <isApp>1</isApp>
      <isDly>0</isDly>
      <flags/>
      <lat>41.85532</lat>
      <lon>-87.63133</lon>
      <heading>176</heading>
    </train>
  </route>
  <route name="blue">
    <train>
      <rn>134</rn>
      <destSt>30077</destSt>
      <destNm>Forest Park</destNm>
      <trDr>5</trDr>
      <nextStaId>40570</nextStaId>
      <nextStpId>30112</nextStpId>
      <nextStaNm>California</nextStaNm>
      <prdt>20180117 22:40:47</prdt>
      <arrT>20180117 22:42:47</arrT>
      <isApp>0</isApp>
      <isDly>0</isDly>
      <flags/>
      <lat>41.92528</lat>
      <lon>-87.70238</lon>
      <heading>122</heading>
    </train>
  </route>
</data>

以下代码获取蓝色或红色的列车编号:

soup = bs4.BeautifulSoup(xml, 'xml')
soup.select_one('route[name="blue"] train rn').get_text()
soup.select_one('route[name="red"] train rn').get_text()

selectselect_one函数允许css选择器(甚至在xml中)选择数据。要过滤标记的属性,请使用tagname[attrname="attrvalue"]

如果要将xml转换为python数据结构,可以使用以下内容:

from typing import *
import bs4


def xml_to_py(soup: bs4.BeautifulSoup) -> Dict[str, Dict[int, Dict[str, str]]]:
    data = {}
    for route in soup.select('route'):
        route_data = data[route.get('name')] = {}
        for train in route.select('train'):
            train_number = int(train.select_one('rn').get_text())
            train_data = {
                tag.name: tag.get_text()
                for tag in
                train.select('*')
            }
            route_data[train_number] = train_data
    return data

使用上面xml的bs4.BeautifulSoup实例调用,会产生这个词典:

{
    'blue': {
        134: {
            'arrT': '20180117 22:42:47',
            'destNm': 'Forest Park',
            'destSt': '30077',
            'flags': '',
            'heading': '122',
            'isApp': '0',
            'isDly': '0',
            'lat': '41.92528',
            'lon': '-87.70238',
            'nextStaId': '40570',
            'nextStaNm': 'California',
            'nextStpId': '30112',
            'prdt': '20180117 22:40:47',
            'rn': '134',
            'trDr': '5'
        }
    },
    'red': {
        830: {
            'arrT': '20180117 22:42:16',
            'destNm': '95th/Dan Ryan',
            'destSt': '30089',
            'flags': '',
            'heading': '176',
            'isApp': '1',
            'isDly': '0',
            'lat': '41.85532',
            'lon': '-87.63133',
            'nextStaId': '41000',
            'nextStaNm': 'Cermak-Chinatown',
            'nextStpId': '30194',
            'prdt': '20180117 22:41:16',
            'rn': '830',
            'trDr': '5'
        }
    }
}