【发布时间】:2011-12-14 20:43:16
【问题描述】:
我目前正在尝试从格式错误的网页中提取信息。具体来说,该页面对多个表格元素使用了相同的 id 属性。标记相当于这样:
<body>
<div id="random_div">
<p>Some content.</p>
<table id="table_1">
<tr>
<td>Important text 1.</td>
</tr>
</table>
<h4>Some heading in between</h4>
<table id="table_1">
<tr>
<td>Important text 2.</td>
<td>Important text 3.</td>
</tr>
</table>
<p>How about some more text here.</p>
<table id="table_1">
<tr>
<td>Important text 4.</td>
<td>Important text 5.</td>
</tr>
</table>
</div>
</body>
显然这是不正确的 HTML 格式,因为一个元素多次使用相同的 id。
我正在使用 XPath 尝试提取各种表格元素中的所有文本,并通过 Scrapy 框架使用该语言。
我的电话,看起来像这样:
hxs.select('//div[contains(@id, "random_div")]//table[@id="table_1"]//text()').extract()
因此 XPath 表达式为:
//div[contains(@id, "random_id")]//table[@id="table_1"]//text()
这将返回:[u'Important text 1.'],即与 id 值“table_1”匹配的第一个表的内容。在我看来,一旦遇到具有特定 id 的元素,它就会忽略标记中将来出现的任何事件。谁能证实这一点?
更新
感谢以下快速回复。我已经在本地托管的页面上测试了我的代码,该页面具有与上述相同的测试格式并返回正确的响应,即
`[u'Important text 1.', u'Important text 2.', . . . . ,u'Important text 5.']`
因此,无论是 Xpath 表达式还是我正在进行的 Python 调用都没有问题。
我猜这意味着网页本身存在问题,要么搞砸了 XPath,要么搞砸了 html 解析器,即libxml2。
有人对我如何深入研究这个有什么建议吗?
更新 2
我已成功隔离问题。它实际上是与底层解析库,即lxml(它为libxml2 C 库提供Python 绑定。
问题在于解析器无法处理垂直制表符。我不知道是谁编写了我正在处理的网站,但它是 full 的垂直标签。 Web 浏览器似乎可以忽略这些,这就是为什么在相关站点上运行来自 Firebug 的 XPath 查询是成功的。
此外,因为上面的简化示例不包含垂直选项卡,所以它可以正常工作。对于在 Scrapy(或一般在 python 中)中遇到此问题的任何人,以下修复对我有用,从 html 响应中删除垂直选项卡:
def parse_item(self, response):
# remove all vertical tabs from the html response
response.body = filter(lambda c: c != "\v", response.body)
hxs = HtmlXPathSelector(response)
items = hxs.select('//div[contains(@id, \"random_div\")]' \
'//table[@id="table_1"]//text()').extract()
【问题讨论】:
-
这是一个广泛的更新......但您可以从检查 HTML Scrapy 提供给您开始。如果这与您在浏览器中查看网站的方式不同,您可能需要调整您的 XPath 选择器。
标签: python xpath html-parsing web-scraping scrapy