2013-03-06 84 views
1

我試圖把蟒蛇從HTML頁面解析這個XML代碼:在Python和XML解析HTML頁面

<weather> 
    <loc mobiurl="http://foreca.mobi/?lon=-8.6110&lat=41.1496&source=navi/" url="http://foreca.com/?lon=-8.6110&lat=41.1496&source=navi/"> 
     <obs station="Porto/Pedras Rubras" dist="11 km NW" dt="2013-03-06 17:00:00" t="14" tf="14" s="d320" wn="S" ws="8" p="997" rh="94" v="5000"/> 
     <fc dt="2013-03-07" tx="16" tn="11" s="d220"/> 
     <fc dt="2013-03-08" tx="15" tn="10" s="d220"/> 
     <fc dt="2013-03-09" tx="15" tn="10" s="d220"/> 
    </loc> 
</weather> 

我想要得到drstxtn領域的信息,但我不知道如何用XML功能來完成它。我嘗試讀取HTML文件,然後創建箭頭並將路徑存儲到之前所說的路徑之後,但我無法使其工作。

有什麼簡單的方法可以用python獲取數據嗎?

+0

我對你的問題有點困惑。這是來自XML文檔還是HTML文檔的數據?如果它來自HTML文檔*,它是如何嵌入的? – 2013-03-06 18:08:35

+1

在這個例子中沒有'tr'屬性,是一個錯字? – 2013-03-06 18:16:15

+1

它不是格式良好的XML。 &符號('&')必須作爲'&'轉義。 – jfs 2013-03-06 18:51:23

回答

0

一些HTML刮容易與pyparsing完成後,使用該庫的makeHTMLTags方法(makeHTMLTags回報表達對,用於打開和關閉標籤,但在你的例子,只需要打開標籤):

from pyparsing import makeHTMLTags 

fcTag = makeHTMLTags("fc")[0] 
tagAttrs = 'dt s tx tn'.split() 

for match in fcTag.searchString(htmltext): 
    print ' '.join("%s:%s" % (attr,match[attr]) for attr in tagAttrs) 

打印:

dt:2013-03-07 s:d220 tx:16 tn:11 
dt:2013-03-08 s:d220 tx:15 tn:10 
dt:2013-03-09 s:d220 tx:15 tn:10 

這使得很容易將這一片段解析器與pyparsing的其他功能,如運行時解析動作,語義檢查等

編輯

如果你希望所有的DT的,S公司等在自己各自的列表中(在Python中,我們稱他們爲 「列表」,而不是 「矢量」),這樣做:

dtArray = [] 
sArray = [] 
txArray = [] 
tnArray = [] 
for match in fcTag.searchString(htmltext): 
    dtArray.append(match.dt) 
    sArray.append(match.s) 
    txArray.append(match.tx) 
    tnArray.append(match.tn) 
    print ' '.join("%s:%s" % (attr,match[attr]) for attr in tagAttrs) 

我以前見過這樣的代碼,它是一個糟糕的數據結構模式。您可以通過獲取dtArray[i],sArray[i]等訪問原始表的第i個條目的值。

請考慮改爲Python提供的幾種結構類型之一。你有幾種可供選擇:

A.使用字典。

fcArray = [] 
for match in fcTag.searchString(htmltext): 
    fcArray.append(dict((attr,match[attr]) for attr in tagAttrs)) 

我們獲得在第i個條目,只得到fc = fcArray[i],並訪問fc['dt']fc['s']等。來自該字典的值。

B.使用namedtuples。

from collections import namedtuple 
FCData = namedtuple("FCData", tagAttrs) 

fcArray = [] 
for match in fcTag.searchString(htmltext): 
    fcArray.append(FCData(*(match[attr] for attr in tagAttrs))) 

您再次使用fc = fcArray[i]獲得第i項,但現在您可以訪問使用fc.dtfc.s,價值觀等等,我覺得這種形式進行的前瞻性清潔比字典的形式,但也有一些限制。所有的標籤名稱都必須是合法的Python標識符,所以如果你有一個標籤「rise/run」,那麼你不能使用namedtuple。此外,namedtuples是不可變的 - 您不能使用現有的FCData fc並將其分配到的dt字段中。另一方面,口述會允許這樣做。 C.使用對象。最簡單的是創建空的對象實例,你不是添加屬性通過簡單的賦值或SETATTR所謂的「袋」型對象:

class FCData(object): pass 

fcArray = [] 
for match in fcTag.searchString(htmltext): 
    fc = FCdata() 
    for attr in tagAttrs: 
     setattr(fc, attr, match[attr]) 
    fcArray.append(fc) 

你得到第i個與fc = fcArray[i]項,像namedtuple ,您可以使用fc.dt等獲得屬性。但是,如果需要,也可以修改屬性,並且指配fc.dt = "new datetime value"可以工作。

D.只需使用由pyparsing的searchString方法創建的對象。

fcArray = fcTag.searchString(htmltext) 

pyparsing回報ParseResults,它結合了字典和namedtuples的行爲。就像在您訪問fc = fcArray[i]的第i個條目之前一樣。您可以使用fc.dtfc['dt']閱讀dt屬性。你可以閱讀fc.dt,但你不能指定它,就像namedtuple一樣。你可以分配到fc['dt'],就像字典。

+0

顯然這是工作。現在我會改變這一點,並嘗試在樹莓派上進行調整。 非常感謝:D – canibalimao 2013-03-07 18:49:50

+0

我試圖「保存」不同的向量中的每個值,但我卡... 我想要一個向量爲每個日期,另一個爲每個「s」等,但我只保存每個元素的最後一行。任何人都可以幫助我? :( – canibalimao 2013-03-07 21:05:35

+0

請參閱我的編輯答案 – PaulMcG 2013-03-08 08:38:47

0

如果您可以輕鬆提取天氣標籤,則可以使用Python附帶的xml.etree.ElementTree API

import xml.etree.ElementTree as ET 
tree = ET.fromstring(weatherdata) 

for fcelem in tree.findall('.//fc'): 
    print fcelem.attrib['tx'], fcelem.attrib['tn'] 

如果你想從HTML文檔中提取它,那麼它取決於HTML的格式。如果它是一個XHTML文檔,ElementTree API可以很好地處理它。

否則,您需要改用HTML解析器。您可以安裝lxml library;該庫支持相同的ElementTree API,但包含專用的HTML解析器。您可以使用BeautifulSoup作爲替代HTML API。實際上,lxmlBeautifulSoup可以協同工作,爲您的任務提供API選擇;使用哪一個更容易爲你。

lxmlBeautifulSoup都是外部庫。

+0

'.fromstring()'返回一個元素,而不是樹。 '.findall('fc')'在這裏不起作用。您可以使用'.findall('。// fc')'或'.iter('fc')'代替。 – jfs 2013-03-06 18:48:41

+0

@ J.F.Sebastian:調整。 – 2013-03-06 18:49:30

+0

或者python發行版中有一個非常簡單的HTMLParser。 – ondra 2013-03-06 18:52:14