繁体   English   中英

使用lxml获取xml数据

[英]Using lxml to get xml data

对您来说,应该是一个容易回答的Python大师问题!

我有要解析的XML信息(来自URL)

<calculateRouteResponse xmlns="http://api.tomtom.com/routing" formatVersion="0.0.12">
<copyright>...</copyright>
<privacy>...</privacy>
<route>
<summary>
<lengthInMeters>5144</lengthInMeters>
<travelTimeInSeconds>687</travelTimeInSeconds>
<trafficDelayInSeconds>0</trafficDelayInSeconds>
<departureTime>2018-01-16T11:16:06+11:00</departureTime>
<arrivalTime>2018-01-16T11:27:33+11:00</arrivalTime>
<noTrafficTravelTimeInSeconds>478</noTrafficTravelTimeInSeconds>
<historicTrafficTravelTimeInSeconds>687</historicTrafficTravelTimeInSeconds>
<liveTrafficIncidentsTravelTimeInSeconds>687</liveTrafficIncidentsTravelTimeInSeconds>
</summary>
<leg>
<summary>
<lengthInMeters>806</lengthInMeters>
<travelTimeInSeconds>68</travelTimeInSeconds>
<trafficDelayInSeconds>0</trafficDelayInSeconds>
<departureTime>2018-01-16T11:16:06+11:00</departureTime>
<arrivalTime>2018-01-16T11:17:14+11:00</arrivalTime>
<noTrafficTravelTimeInSeconds>59</noTrafficTravelTimeInSeconds>
<historicTrafficTravelTimeInSeconds>68</historicTrafficTravelTimeInSeconds>
<liveTrafficIncidentsTravelTimeInSeconds>68</liveTrafficIncidentsTravelTimeInSeconds>
</summary>
<points>...</points>
</leg>
<leg>
<summary>
<lengthInMeters>958</lengthInMeters>
<travelTimeInSeconds>114</travelTimeInSeconds>
<trafficDelayInSeconds>0</trafficDelayInSeconds>
<departureTime>2018-01-16T11:17:14+11:00</departureTime>
<arrivalTime>2018-01-16T11:19:08+11:00</arrivalTime>
<noTrafficTravelTimeInSeconds>77</noTrafficTravelTimeInSeconds>
<historicTrafficTravelTimeInSeconds>114</historicTrafficTravelTimeInSeconds>
<liveTrafficIncidentsTravelTimeInSeconds>114</liveTrafficIncidentsTravelTimeInSeconds>
</summary>
<points>...</points>
</leg>
<leg>
<summary>
<lengthInMeters>1798</lengthInMeters>
<travelTimeInSeconds>224</travelTimeInSeconds>
<trafficDelayInSeconds>0</trafficDelayInSeconds>
<departureTime>2018-01-16T11:19:08+11:00</departureTime>
<arrivalTime>2018-01-16T11:22:53+11:00</arrivalTime>
<noTrafficTravelTimeInSeconds>181</noTrafficTravelTimeInSeconds>
<historicTrafficTravelTimeInSeconds>224</historicTrafficTravelTimeInSeconds>
<liveTrafficIncidentsTravelTimeInSeconds>224</liveTrafficIncidentsTravelTimeInSeconds>
</summary>
<points>...</points>
</leg>
<leg>
<summary>
<lengthInMeters>1582</lengthInMeters>
<travelTimeInSeconds>280</travelTimeInSeconds>
<trafficDelayInSeconds>0</trafficDelayInSeconds>
<departureTime>2018-01-16T11:22:53+11:00</departureTime>
<arrivalTime>2018-01-16T11:27:33+11:00</arrivalTime>
<noTrafficTravelTimeInSeconds>160</noTrafficTravelTimeInSeconds>
<historicTrafficTravelTimeInSeconds>280</historicTrafficTravelTimeInSeconds>
<liveTrafficIncidentsTravelTimeInSeconds>280</liveTrafficIncidentsTravelTimeInSeconds>
</summary>
<points>...</points>
</leg>
<sections>
<section>
<startPointIndex>0</startPointIndex>
<endPointIndex>139</endPointIndex>
<sectionType>TRAVEL_MODE</sectionType>
<travelMode>car</travelMode>
</section>
</sections>
</route>
</calculateRouteResponse>

我有这个脚本,试图用来获取特定信息。

from lxml import etree
import urllib.request

def parseXML(xmlFile):
    """
    Parse the xml
    """
    with urllib.request.urlopen("https://api.tomtom.com/routing/1/calculateRoute/-37.79205923474775,145.03010268799338:-37.798883995180496,145.03040309540322:-37.807106781970354,145.02895470253526:-37.80320743019992,145.01021142594075:-37.79990,144.99318476311566:?routeType=shortest&key=xxxx&computeTravelTimeFor=all") as fobj:
        xml = fobj.read()
#Look at Parent and Child XML organisation as this is where the data is going wrong at the moment
    root = etree.fromstring(xml)

    for appt in root.getchildren():
        for elem in appt.getchildren():
            if not elem.text:
                text = "None"
            else:
                text = elem[0][0].text

            ##This is doing something with the xml based on it's tag and value.
            if elem.tag == 'travelTimeInSeconds' and int(text) > 700:
                print('******** Do something with ', elem.tag, ' : ', text)
            print(elem.tag + " => " + text)

if __name__ == "__main__":
    parseXML("example.xml")

我得到的输出仅来自“摘要”和“腿”选项卡。

所以EG

期望的输出是这个

<summary>
<lengthInMeters>5144</lengthInMeters>
<travelTimeInSeconds>687</travelTimeInSeconds>
<trafficDelayInSeconds>0</trafficDelayInSeconds>
<departureTime>2018-01-16T11:16:06+11:00</departureTime>
<arrivalTime>2018-01-16T11:27:33+11:00</arrivalTime>
<noTrafficTravelTimeInSeconds>478</noTrafficTravelTimeInSeconds>
<historicTrafficTravelTimeInSeconds>687</historicTrafficTravelTimeInSeconds>
<liveTrafficIncidentsTravelTimeInSeconds>687</liveTrafficIncidentsTravelTimeInSeconds>
</summary>

而每条腿,如果可能的话(所以->

<leg>
<summary>
<lengthInMeters>958</lengthInMeters>
<travelTimeInSeconds>114</travelTimeInSeconds>
<trafficDelayInSeconds>0</trafficDelayInSeconds>
<departureTime>2018-01-16T11:17:14+11:00</departureTime>
<arrivalTime>2018-01-16T11:19:08+11:00</arrivalTime>
<noTrafficTravelTimeInSeconds>77</noTrafficTravelTimeInSeconds>
<historicTrafficTravelTimeInSeconds>114</historicTrafficTravelTimeInSeconds>
<liveTrafficIncidentsTravelTimeInSeconds>114</liveTrafficIncidentsTravelTimeInSeconds>
</summary>
</leg>

XML标签之间的数据,例如1582,以米为单位的长度

如何更改此脚本以从长度计,旅行时间秒数和那些特定的孩子那里获取信息? 特别想要摘要标签中的内容,最有价值的信息,谢谢!

感谢您的时间!

这是基于我得到的答案和我自己的解释的解决方案。

现在开始格式化数据,然后学习如何对其进行腌制!

from lxml import etree
import urllib.request

def handleLeg(leg):
    # print this leg as text, or save it to file maybe...
    text = etree.tostring(leg, pretty_print=True)
    print (text)
    # also process individual elements of interest here if we want
    tagsOfInterest=["noTrafficTravelTimeInSeconds", "lengthInMeters", "departureTime", "trafficDelayInSeconds"]  # whatever
    for child in leg:
        if 'summary' in child.tag:
           for elem in child:
               for item in tagsOfInterest:
                   if item in elem.tag:
                       print (item + " : " + elem.text)

def parseXML(xmlFile):
    """
    Parse the xml
    """
    with urllib.request.urlopen("https://api.tomtom.com/routing/1/calculateRoute/-37.79205923474775,145.03010268799338:-37.798883995180496,145.03040309540322:-37.807106781970354,145.02895470253526:-37.80320743019992,145.01021142594075:-37.79990,144.99318476311566:?routeType=shortest&key=xxxxx&computeTravelTimeFor=all") as fobj:
        xml = fobj.read()
#Look at Parent and Child XML organisation as this is where the data is going wrong at the moment
    root = etree.fromstring(xml)

    for child in root:
        if 'route' in child.tag:
            for elem in child:
                if 'leg' in elem.tag:
                    handleLeg(elem)



if __name__ == "__main__":
    parseXML("example.xml")




'''
import pickle
favorite_color = { "lion": "yellow", "kitty": "red" }

pickle.dump( favorite_color, open( "save.p", "wb" ) )
'''

我的理解是parseXML从网站获取数据,然后变成etree,然后在解析之前先搜索“ route”和“ leg”。 感兴趣的标签用于找到正确的文本以显示在解释器中。

尝试确保我也有“摘要”选项卡。

下一步是将该信息放入类/对象/字典中,并整理以供将来使用。

我没有访问TomTom API的权限,因此无法按发布的方式运行您的所有代码,但是确实查看了您发布的XML字符串。

下面是一些我用来提取各个“腿”元素并对其进行处理的代码。 我只是将它们打印为文本(可以将它们另存为文件),还提取了特定的子项并将其打印出来。

从您的问题中尚不清楚您究竟想对数据做什么,但是也许这为您提供了一个工作的起点。

from lxml import etree
import urllib.request

xml = '<calculateRouteResponse xmlns="http://api.tomtom.com/routing" formatVersion="0.0.12">\
<copyright>...</copyright>\
<privacy>...</privacy>\
<route>\
<summary>\
<lengthInMeters>5144</lengthInMeters>\
<travelTimeInSeconds>687</travelTimeInSeconds>\
<trafficDelayInSeconds>0</trafficDelayInSeconds>\
<departureTime>2018-01-16T11:16:06+11:00</departureTime>\
<arrivalTime>2018-01-16T11:27:33+11:00</arrivalTime>\
<noTrafficTravelTimeInSeconds>478</noTrafficTravelTimeInSeconds>\
<historicTrafficTravelTimeInSeconds>687</historicTrafficTravelTimeInSeconds>\
<liveTrafficIncidentsTravelTimeInSeconds>687</liveTrafficIncidentsTravelTimeInSeconds>\
</summary>\
<leg>\
<summary>\
<lengthInMeters>806</lengthInMeters>\
<travelTimeInSeconds>68</travelTimeInSeconds>\
<trafficDelayInSeconds>0</trafficDelayInSeconds>\
<departureTime>2018-01-16T11:16:06+11:00</departureTime>\
<arrivalTime>2018-01-16T11:17:14+11:00</arrivalTime>\
<noTrafficTravelTimeInSeconds>59</noTrafficTravelTimeInSeconds>\
<historicTrafficTravelTimeInSeconds>68</historicTrafficTravelTimeInSeconds>\
<liveTrafficIncidentsTravelTimeInSeconds>68</liveTrafficIncidentsTravelTimeInSeconds>\
</summary>\
<points>...</points>\
</leg>\
<leg>\
<summary>\
<lengthInMeters>958</lengthInMeters>\
<travelTimeInSeconds>114</travelTimeInSeconds>\
<trafficDelayInSeconds>0</trafficDelayInSeconds>\
<departureTime>2018-01-16T11:17:14+11:00</departureTime>\
<arrivalTime>2018-01-16T11:19:08+11:00</arrivalTime>\
<noTrafficTravelTimeInSeconds>77</noTrafficTravelTimeInSeconds>\
<historicTrafficTravelTimeInSeconds>114</historicTrafficTravelTimeInSeconds>\
<liveTrafficIncidentsTravelTimeInSeconds>114</liveTrafficIncidentsTravelTimeInSeconds>\
</summary>\
<points>...</points>\
</leg>\
<leg>\
<summary>\
<lengthInMeters>1798</lengthInMeters>\
<travelTimeInSeconds>224</travelTimeInSeconds>\
<trafficDelayInSeconds>0</trafficDelayInSeconds>\
<departureTime>2018-01-16T11:19:08+11:00</departureTime>\
<arrivalTime>2018-01-16T11:22:53+11:00</arrivalTime>\
<noTrafficTravelTimeInSeconds>181</noTrafficTravelTimeInSeconds>\
<historicTrafficTravelTimeInSeconds>224</historicTrafficTravelTimeInSeconds>\
<liveTrafficIncidentsTravelTimeInSeconds>224</liveTrafficIncidentsTravelTimeInSeconds>\
</summary>\
<points>...</points>\
</leg>\
<leg>\
<summary>\
<lengthInMeters>1582</lengthInMeters>\
<travelTimeInSeconds>280</travelTimeInSeconds>\
<trafficDelayInSeconds>0</trafficDelayInSeconds>\
<departureTime>2018-01-16T11:22:53+11:00</departureTime>\
<arrivalTime>2018-01-16T11:27:33+11:00</arrivalTime>\
<noTrafficTravelTimeInSeconds>160</noTrafficTravelTimeInSeconds>\
<historicTrafficTravelTimeInSeconds>280</historicTrafficTravelTimeInSeconds>\
<liveTrafficIncidentsTravelTimeInSeconds>280</liveTrafficIncidentsTravelTimeInSeconds>\
</summary>\
<points>...</points>\
</leg>\
<sections>\
<section>\
<startPointIndex>0</startPointIndex>\
<endPointIndex>139</endPointIndex>\
<sectionType>TRAVEL_MODE</sectionType>\
<travelMode>car</travelMode>\
</section>\
</sections>\
</route>\
</calculateRouteResponse>'


def handleLeg(leg):
    """
    Handle a single leg element pulled from the main xml block
    """
    # now that we have a leg element, we can handle it as we want.
    # first, print this leg as text, so as we can see what it contains
    # NB we could also just append this text block to a file of "legs"
    text = etree.tostring(leg, pretty_print=True) 
    print (text)
    # we can see that there are individual elements of interest,
    # held within the "summary" child element
    # for each element of interest, extract the data and print it
    tagsOfInterest=["noTrafficTravelTimeInSeconds", "lengthInMeters", "departureTime"]  # whatever
    for child in leg:
        if 'summary' in child.tag:
            # we've found the "summary" child
            # so inspect each of its child element tags
            # to see if it is of interest
            for elem in child:
               for item in tagsOfInterest:
                   if item in elem.tag:
                       # its of interest...
                       # print it here
                       print (item + " : " + elem.text)

def parseXML(xml):
    """
    Parse the xml
    """
    root = etree.fromstring(xml)
    # look for the main "route" element, there should only be one...
    # do this by checking if the text "route" appears in the element tag
    for child in root:
        if 'route' in child.tag:
            # OK we found a/the route element. Now iterate over its "leg"
            # elements and handle each one
            for elem in child:
                if 'leg' in elem.tag:
                    # this is a "leg" element so handle it 
                    handleLeg(elem)    

if __name__ == "__main__":
    parseXML(xml)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM