【问题标题】:Excluding specific child node with XPath and Scrapy/lxml使用 XPath 和 Scrapy/lxml 排除特定子节点
【发布时间】:2016-07-31 18:13:33
【问题描述】:

我有一些使用 scrapy 抓取 bbcode 论坛的 Python 代码,我需要一个 Xpath 表达式,它只给我帖子的文本,不包括引号中的文本。 HTML 如下所示:

<td class="postbody">
   hi this is a response
   <div class="bbc-block">
      <blockquote>
         blah blah blah here's a quote
         <br>
      </blockquote>
   </div>
   <br>
   and now I'm responding to what I quoted
</td>
<td class="postbody">
   <div class="bbc-block">
      <blockquote>
         and now I'm responding to what I quoted
         <br>
      </blockquote>
   </div>
   <br>
   wow what a great response
</td>

对于每个帖子,每个页面都会发生多次。我最终想要的只是每个 td 节点的文本,不包括块引用:

  1. 您好,这是一个回复\n,现在我正在回复我引用的内容
  2. 哇,好棒的回应

我必须提取这些块的 Python 代码如下——首先我将它从 scrapy 的 HtmlResponse 转换为 lxml 的 HtmlElement 类,因为这是我想出使用 lxml.html.text_content() 方法的唯一方法:

import lxml.html as ht

def posts_from_response(self, response):
    dom = ht.fromstring(response.body)
    posts = dom.xpath('//td[@class="postbody"]')
    posts_text = [p.text_content() for p in posts]
    return posts_text

这几天我已经广泛搜索了解决方案,并尝试了大约十几种变体

'//td[@class="postbody"][not(@class="bbc-block")]'

以各种方式附加到它,但没有什么能通过我想要的分组得到我想要的。

是否有 1. 一种通过单个语句获取此信息的方法,或者 2. 一种在我的 posts 列表上执行第二个 Xpath 选择器以排除 bbc-block 节点的方法?

【问题讨论】:

    标签: python html xpath scrapy


    【解决方案1】:

    仅获取 try 的直接子文本:

    //*[@class='postbody']/text()  
    

    获取 td 中的所有文本元素,但忽略 div 中的文本,类 bbc-block':

     //td//text()[not(ancestor::*[@class='bbc-block'])]"
    

    【讨论】:

    • 谢谢!!第二条语句有效(尽管有一些小的语法更改)。我将 .extract() 添加到我的第一个 xpath() 调用中,然后迭代 unicode 结果,创建 HtmlElement 对象并将该语句应用于它们。
    猜你喜欢
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 2016-06-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多