今天我尝试了lxml,因为我从特定的Web服务获得了非常讨厌的html输出,我不想使用re模块,只是为了改变并学习新东西。我做了,并行浏览http://codespeak.net/lxml/和http://stackoverflow.com
我不会尝试解释上面的html模板,但只是为了概述它充满了故意嵌套的表。
我用html解析器然后find_class()提取了一部分感兴趣的东西,并用xpath迭代TR(甚至这个TR里面都有表)。 现在我正在尝试根据class和id属性提取数据对:
代码看起来像这样:
fragment = root.find_class('foo')
for node in fragment[0].xpath('table[2]/tr'):
name = node.xpath('//div[@id="title"]')
value = node.xpath('//td[@class="text"]')
问题在于,并非每个TR,我正在迭代,都有这些对:有些只有名称(id“title”),所以稍后当我尝试压缩它们时,我会错误地配对数据。
我尝试了一些我想到的事情,但没有成功:我试图比较列表长度(名称和值),如果它们与跳过名称查找不匹配,那么如果它们不匹配,则删除最后一个列表项(在很多方面)但没有任何效果。例如:
if not len(name) == len(value):
name.pop()
或
if len(name) == len(value):
name = node.xpath('//div[@id="title"]')
value = node.xpath('//td[@class="text"]')
更有经验的一些评论?
答案 0 :(得分:4)
这是怎么回事?
from lxml import etree
doc = etree.HTML(open('test.data').read())
for t in doc.xpath('//table[.//div[@id="title"] and .//td[@class="text"]]'):
print etree.tostring(t.xpath('.//div[@id="title"]')[0])
print etree.tostring(t.xpath('.//td[@class="text"]')[0])
print "--"
产量:
<div id="title">
<span class="Browse">string</span>
</div>
<td class="text" style="padding-left:5px;">
<a href="/***/***.dll?p=***&sql=xxx:yyy">string</a>
</td>
--
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
<a href="/***/***.dll?p=***&sql=xxx:yyy">string</a>
</td>
--
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
Gospodar of Lutaka
</td>
--
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
1986
</td>
--
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
Sep 1985-Dec 1985
</td>
--
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
Elektra
</td>
--
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
54:51
</td>
--
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
</td>
--
更新,扩展了xpath表达式的前导部分,以消除不需要的结果。感谢Alejandro指出这一点,并提出了一个似乎不适用于otrov的解决方案。
from urllib2 import urlopen
from lxml import etree
doc = etree.HTML(urlopen('http://pastebin.com/download.php?i=cg5HHJ6x').read())
for t in doc.xpath('//table/tr/td/table[.//div[@id="title"] and .//td[@class="text"]]'):
print etree.tostring(t.xpath('.//div[@id="title"]')[0])
print etree.tostring(t.xpath('.//td[@class="text"]')[0])
print "--"
答案 1 :(得分:0)
现在,通过输入样本,您可以更清楚地了解所要求的内容。
只有这一个XPath 1.0表达式返回一个带有div
和td
对的节点集(按文档顺序):
/table/tr/td/table[tr/td/div[@id='title']]
[tr/td[@class='text']]
/tr//*[self::div[@id='title'] or self::td[@class='text']]
作为证明,这个样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<result>
<xsl:copy-of
select="/table/tr/td/table[tr/td/div[@id='title']]
[tr/td[@class='text']]
/tr//*[self::div[@id='title'] or
self::td[@class='text']]"/>
</result>
</xsl:template>
</xsl:stylesheet>
输出(正确的输入样本,因为您错过了结束td
):
<result>
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
<a href="/***/***.dll?p=***&sql=xxx:yyy">string</a>
</td>
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
Gospodar of Lutaka
</td>
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
1986
</td>
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
Sep 1985-Dec 1985
</td>
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
Elektra
</td>
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;">
54:51
</td>
<div id="title">
<span>string</span>
</div>
<td class="text" style="padding-left:5px;"></td>
</result>