代码之家  ›  专栏  ›  技术社区  ›  user2278224

Python XML解析失败

  •  0
  • user2278224  · 技术社区  · 11 年前

    我有一个简单的函数来从站点检索XML,并将其存储在字符串中:

    def market(typeid):
      ping = urllib2.urlopen('http://api.eve-central.com/api/marketstat?usesystem=30000142&typeid=' + str(typeid))
      info = ping.read()
      return info
    

    然后,我使用ElementTree库来解析XML,但这不起作用,完全没有错误,但它似乎认为XML代码只有几行长,就到此为止,而还有更多的元素。我正在寻找远低于前几个元素的元素,但在前几个元素之后它就停止了,以为它已经到达了文档的结尾或其他什么?我在网上找了很长一段时间都不太明白,没有发现什么有用的东西。在shell中打印的XML如下:

    <?xml version='1.0' encoding='utf-8'?>
    <evec_api version="2.0" method="marketstat_xml">
      <marketstat><type id="34">
          <buy><volume>14082197693</volume><avg>5.61</avg><max>5.89</max><min>4.61</min><stddev>0.46</stddev><median>5.57</median><percentile>5.87</percentile></buy>
          <sell><volume>19614612791</volume><avg>6.31</avg><max>10.00</max><min>5.90</min><stddev>0.64</stddev><median>6.15</median><percentile>6.00</percentile></sell>
          <all><volume>34096810484</volume><avg>5.95</avg><max>10.00</max><min>0.50</min><stddev>0.84</stddev><median>6.03</median><percentile>4.26</percentile></all>
        </type></marketstat>
    </evec_api>
    

    要开始我正在使用的解析

    root = ET.fromstring(data)
    

    并将ElementTree作为ET导入。根据我所读到的,这是将XML作为字符串而不是文件“注入”的唯一方法。我想,如果有一种简单的方法可以将文件下载到临时位置,并使用文件版本,这也会奏效,但我对这一点束手无策。

    运行时 print ET.tostring(root) 我得到:

    <evec_api method="marketstat_xml" version="2.0">
      <marketstat><type id="34">
          <buy><volume>19627488095</volume><avg>5.69</avg><max>5.91</max>    <min>4.61</min><stddev>0.44</stddev><median>5.81</median><percentile>5.90</percentile></buy>
          <sell><volume>18831805139</volume><avg>6.32</avg><max>10.00</max><min>6.00</min><stddev>0.66</stddev><median>6.15</median><percentile>6.01</percentile></sell>
          <all><volume>38859293234</volume><avg>5.94</avg><max>10.00</max><min>0.50</min><stddev>0.85</stddev><median>5.91</median><percentile>4.26</percentile></all>
        </type></marketstat>
    </evec_api>
    
    2 回复  |  直到 11 年前
        1
  •  0
  •   salparadise    11 年前

    需要更多关于如何尝试的详细信息,但这里有一个遍历DOM树的示例:

    In [339]: %cpaste
    Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
    :x = """
    :<evec_api version="2.0" method="marketstat_xml">
    :  <marketstat><type id="34">
    :      <buy><volume>14082197693</volume><avg>5.61</avg><max>5.89</max><min>4.61</min><stddev>0.46</stddev><median>5.57</median><percentile>5.87</percentile></buy>
    :      <sell><volume>19614612791</volume><avg>6.31</avg><max>10.00</max><min>5.90</min><stddev>0.64</stddev><median>6.15</median><percentile>6.00</percentile></sell>
    :      <all><volume>34096810484</volume><avg>5.95</avg><max>10.00</max><min>0.50</min><stddev>0.84</stddev><median>6.03</median><percentile>4.26</percentile></all>
    :    </type></marketstat>
    :</evec_api>"""
    :<EOF>
    
    In [340]: root = ET.fromstring(x)
    In [342]: [(xx.text,xx.tag) for xx in root.iter()]
    Out[342]: [('\n  ', 'evec_api'), (None, 'marketstat'), ('\n      ', 'type'), (None, 'buy'), ('14082197693', 'volume'), ('5.61', 'avg'), ('5.89', 'max'), ('4.61', 'min'), ('0.46', 'stddev'), ('5.57', 'median'), ('5.87', 'percentile'), (None, 'sell'), ('19614612791', 'volume'), ('6.31', 'avg'), ('10.00', 'max'), ('5.90', 'min'), ('0.64', 'stddev'), ('6.15', 'median'), ('6.00', 'percentile'), (None, 'all'), ('34096810484', 'volume'), ('5.95', 'avg'), ('10.00', 'max'), ('0.50', 'min'), ('0.84', 'stddev'), ('6.03', 'median'), ('4.26', 'percentile')]
    
        2
  •  0
  •   user2278224    11 年前

    @salparadise我现在已经开始工作了,并在一定程度上了解它是如何工作的。代码为:

    root = ET.fromstring(data)
    for buy in root.iter('buy'):
      av = buy.find('avg').text
    avg = float(av)
    print avg
    

    就像一个魅力。谢谢各位!我认为,该教程令人困惑的地方在于,它假设根只有一个子集,所以它给人一种错觉,一切都可以从根的子集解析,然而在我的XML中,根只有一个直接的子集,这对于数据来说是非常无用的,然而,该子集将所有数据保存在它下面的子层中。因此,root.iter函数。