在python中使用XML解析html页面

时间:2013-03-06 18:05:14

标签: python html xml parsing

我正在尝试让python从HTML页面解析这个XML代码:

<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获取数据?

2 个答案:

答案 0 :(得分: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都是外部库。

答案 1 :(得分:0)

使用该库的makeHTMLTags方法(makeHTMLTags返回一对表达式,用于打开和关闭标记,使用pyparsing可以轻松完成一些HTML抓取,但在您的示例中,只需要开始标记):

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提供的几种结构化类型之一。你有几个可供选择:

一个。使用dicts。

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等访问这些值。我发现这个表单看起来比dict形式,但有一些限制。所有标记名称都必须是合法的Python标识符,因此如果您有一个标记“上升/运行”,那么您就不能使用namedtuple。此外,namedtuples是不可变的 - 您无法获取现有的FCData fc并使用dt分配到其fc.dt = "new datetime value"字段中。另一方面,dicts会允许这样做。

℃。使用对象。最简单的是一个“bag”类型的对象,它创建空对象实例,而不是通过简单的赋值或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)

您可以使用fc = fcArray[i]获取第i个条目,并且像namedtuple一样,您可以使用fc.dt获取属性,依此类推。但是,如果需要,您还可以修改属性,分配fc.dt = "new datetime value"将起作用。

d。只需使用pyparsing的searchString方法创建的对象。

fcArray = fcTag.searchString(htmltext)

pyparsing返回ParseResults,它结合了dicts和namedtuples的行为。就像在使用fc = fcArray[i]访问第i个条目之前一样。您可以使用dtfc.dt阅读fc['dt']属性。您可以阅读fc.dt,但无法分配给它,就像namedtuple一样。 可以分配给fc['dt'],就像字典一样。