2013-03-06 252 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