2012-06-26 101 views
-2

我在Python中使用urllib2和sre解析aprs.fi中的數據,以便我可以在正在處理的某些實時高空氣球代碼中使用天氣數據。解析代碼非常簡單:解析網頁中的sre.findall()

import urllib2 
import sre 

APRStracking = urllib2.urlopen("http://api.aprs.fi/api/get?name=KD8REX&what=loc&apikey=42457.M4AFa3hdkXG31&format=xml") 

APRSxml = APRStracking.read() 

latitude = sre.findall('<la.*>(.*)</la.*>', APRSxml) 
print latitude 

我試圖解析的數據是XML,它看起來像:

<xml> 
    <command>get</command> 
    <result>ok</result> 
    <what>loc</what> 
    <found>1</found> 
    <entries> 
     <entry> 
     <name>KD8REX</name> 
     <type>l</type> 
     <time>1339339410</time> 
     <lasttime>1339339410</lasttime> 
     <lat>41.95550</lat> 
     <lng>-83.65567</lng> 
     <altitude>2204.62</altitude> 
     <course>15</course> 
     <speed>15</speed> 
     <symbol>/O</symbol> 
     <srccall>KD8REX</srccall> 
     <dstcall>APT311</dstcall> 
     <status>UofM H.A.S. - Go Blue!</status> 
     <status_lasttime>1339339600</status_lasttime> 
     <path>WIDE1-1,WIDE3-3,qAR,W8SGZ</path> 
     </entry> 
    </entries> 
</xml> 

我並不十分熟悉Python,但我的理解ser.findall()是通過APRSxml查找與正則表達式匹配的任何字符串,然後在列表「緯度」中追加括號之間的任何內容。因此,在本例中,與正則表達式匹配的兩個值分別是「lasttime」和「lat」。但是,當我運行此代碼時,它只輸出<lat>值,而不是<lasttime>。坦率地說,這就是我真正需要的代碼工作,但出於好奇,如果有人能告訴我爲什麼它不像預期的那樣行事,我會很感激。謝謝。

+2

它產生預期的輸出爲我。另外,你爲什麼使用'sre'而不是're'? – BrenBarn

+0

我其實只是意識到我正在使用一個不推薦的模塊哈哈......但無論改變爲重新我仍然只獲得緯度值。 – ricewhite

+0

你應該檢查APRSxml的價值是你認爲它是什麼(通過'print'ing,也許)。正如我所說,當我運行你的代碼'findall'時會返回兩個值。 – BrenBarn

回答

0

您需要將貪婪星星更改爲懶惰匹配(*?)。

>>> re.findall('<la.*?>(.*?)</la.*?>', APRSxml) 
['1339339410', '41.95550'] 

目前發生什麼是<la.*>與從第一la>的最後一次出現仍然允許表達其餘找到匹配的一切。因此,<la.*>匹配

<lasttime>1339339410</lasttime><lat> 

解釋爲什麼不報告上次值。

+0

除非設置了DOTALL標誌,否則不應該如此。 – BrenBarn

+0

@BrenBarn:urllib返回的xml不包含換行符。 – Junuxx

+0

你是對的,原來的文章沒有準確地說出數據是什麼。 – BrenBarn

0

試試這個非貪婪版本:

latitude = re.findall('<la.*?>(.*?)</la.*?', APRSxml) 
>>> print latitude 
['1339339410', '41.95550'] 

但是如果你想「緯度」爲什麼不這樣做呢?

latitude = re.findall('<lat>(.*?)<', APRSxml) 
+0

Ahhhhh,這是訣竅,謝謝!我知道只要匹配就足以滿足我的需求,但我對Python不太熟悉,而且我認爲學習的一個好方法就是用語言來欺騙。這只是一個小問題,我無法弄清楚。 – ricewhite

+0

如果你正在尋找一個更好的解決方案來解析XML與正則表達式(肯定**不推薦),看看你的[Blender發現](http://stackoverflow.com/a/11200728/21945)爲你。 – mhawke

4

看着form參數,我注意到你可以指定form=xml。我將其更改爲json並查看該內容,即可獲得JSON!

{ 
    "command":"get", 
    "result":"ok", 
    "what":"loc", 
    "found":1, 
    "entries":[ 
    { 
     "name":"KD8REX", 
     "type":"l", 
     "time":"1339339410", 
     "lasttime":"1339339410", 
     "lat":"41.95550", 
     "lng":"-83.65567", 
     "altitude":"2204.62", 
     "course":"15", 
     "speed":"15", 
     "symbol":"\/O", 
     "srccall":"KD8REX", 
     "dstcall":"APT311", 
     "status":"UofM H.A.S. - Go Blue!", 
     "status_lasttime":"1339339600", 
     "path":"WIDE1-1,WIDE3-3,qAR,W8SGZ" 
    } 
    ] 
} 

這很容易解析。比XML更容易:

import urllib2, json 

url = 'http://api.aprs.fi/api/get?name=KD8REX&what=loc&apikey=42457.M4AFa3hdkXG31&format=json' 
data = json.loads(urllib2.urlopen(url).read()) 

for entry in data['entries']: 
    print 'Latitude:', entry['lat'] 

這很容易處理。 data只是一個Python字典。

+0

解決手頭問題的最佳解決方案。我不能給這個足夠的+1。 –

+0

斑點... – mhawke

0

的Python包括非常適合承擔這一任務的易於使用的XML解析器:

>>> import urllib2 
>>> from xml.etree.ElementTree import parse 
>>> APRStracking = urllib2.urlopen("http://api.aprs.fi/api/get?name=KD8REX&what=loc&apikey=42457.M4AFa3hdkXG31&format=xml") 
>>> tree = parse(APRStracking) 
>>> tree.find('entries/entry/lat').text 
'41.95550'