我目前正在尝试从格式错误的网页中提取信息。具体来说,页面对多个表元素使用了相同的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绑定。
问题是解析器无法处理垂直选项卡。我不知道是谁编写了我正在处理的网站,但它是完整的垂直标签。 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()
答案 0 :(得分:1)
使用Firebug,这个表达式:
//table[@id='table_1']//td/text()
给了我这个:
[<TextNode textContent="Important text 1.">,
<TextNode textContent="Important text 2.">,
<TextNode textContent="Important text 3.">,
<TextNode textContent="Important text 4.">,
<TextNode textContent="Important text 5.">]
我包含td
过滤以提供更好的结果,否则,您将获得标记之间的空格和换行符。但总而言之,它似乎有效。
我注意到您查询的是//div[contains(@id, "random_id")]
,而您的HTML代码段的标记显示为<div id="random_div">
- _id
和_div
不同。我不知道Scrapy所以我不能说这是否有所作为,但这也不是你的问题吗?
答案 1 :(得分:0)
count(//div[@id = "random_div"]/table[@id= "table_1"])
此xpath为您的示例输入返回3。所以你的问题不在于xpath本身,而在于你用来提取节点的函数。