【问题标题】:How to make XPath select multiple table elements with identical id attributes?如何使 XPath 选择具有相同 id 属性的多个表元素?
【发布时间】: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


【解决方案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 sn-p 有一个标记为&lt;div id="random_div"&gt;——_id_div 是不同的。我不了解 Scrapy,所以我真的不能说它是否有什么作用,但这难道不是你的问题吗?

【讨论】:

  • random_id / random_div 是一种类型。我已经在问题中纠正了它。谢谢。
  • 将其标记为正确,因为它引导我进入 Firebug,然后引导我发现垂直选项卡问题!
【解决方案2】:
count(//div[@id = "random_div"]/table[@id= "table_1"])

此 xpath 为您的示例输入返回 3。所以你的问题不在于 xpath 本身,而在于你用来提取节点的函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 2010-11-03
    • 2012-11-30
    • 2017-09-22
    • 2015-07-06
    相关资源
    最近更新 更多