【问题标题】:How do you delete a subelement from a Scrapy Selector?如何从 Scrapy Selector 中删除子元素?
【发布时间】:2021-11-09 05:03:09
【问题描述】:

我正在尝试使用 Scrapy 抓取一些论坛帖子的内容,并且我想排除从以前的帖子中引用的文本。我很幸运,该网站非常清楚地标记了这个引用的文本(它在“blockquote”标签内),但我无法弄清楚如何在 blockquote 标签中获取所有 not 的文本。下面有一个论坛帖子结构的示例。在这个特定的帖子中,用户写了一些东西,然后引用了之前的帖子,然后再写了一些。所以基本上,我想要摆脱的标签夹在我想要的内容之间。更常见的情况是,引用的文本在前,新的文本紧随其后,但我也需要能够处理这种奇怪的情况。

我尝试使用 w3lib remove_tags:

from w3lib.html import remove_tags, remove_tags_with_content    
body = post.css('div.bbWrapper')[0]
content = remove_tags(remove_tags_with_content(body, ('blockquote', )))

但我得到一个错误:TypeError: to_unicode must receive a bytes, str or unicode object, got Selector

我找到了有关如何使用 Beautiful Soup 执行此操作的说明,但没有找到 Scrapy。如果使用 BS 是唯一的选择,我可以在我的 Scrapy 解析项目方法中间切换到它吗?

<article ...>
<div class="bbWrapper">TEXT I WANT TO COLLECT HERE<br>
<blockquote ...>
    <div class="bbCodeBlock-title">
    <a href="/forums/goto/post?id=1053788123" ...">OTHER GUY SAID:</a>
    </div>
    <div class="bbCodeBlock-content">
    <div class="bbCodeBlock-expandContent js-expandContent ">
    <b>TEXT I DON'T WANT<br>
    <br>
    TEXT I DON'T WANT</b>
    </div>
     <div class="bbCodeBlock-expandLink js-expandLink"><a role="button" tabindex="0">TEXT I DON'T WANT</a></div>
     </div>
    </blockquote>
TEXT I WANT</div>
<div class="js-selectToQuoteEnd">&nbsp;</div>
<div style="margin:10px 0 10px 0;">
...
</div>
</article>

【问题讨论】:

    标签: python web-scraping scrapy


    【解决方案1】:

    首先在你给出的例子中,如果我只选择我得到的 div 内的文本:

    In [1]: response.xpath('.//div/text()').getall()
    Out[1]:
    ['TEXT I WANT TO COLLECT HERE',
     '\r\n',
     '\r\n    ',
     '\r\n    ',
     '\r\n    ',
     '\r\n    ',
     '\r\n    ',
     '\r\n     ',
     '\r\n     ',
     '\r\nTEXT I WANT',
     '\xa0',
     '\r\n...\r\n']
    

    所以你可以这样做:

    In [2]: [x.strip() for x in response.xpath('.//div/text()').getall() if x.strip()]
    Out[2]: ['TEXT I WANT TO COLLECT HERE', 'TEXT I WANT', '...']
    

    甚至更好不要选择它(搜索所有没有 div class="bbCodeBlock-title" 祖先或自身的 div 标签):

    In [3]: response.xpath('//div//text()[not(ancestor-or-self::div[contains(@class,"bbCodeBlock")])]').getall()
    Out[3]:
    ['TEXT I WANT TO COLLECT HERE',
     '\r\n',
     '\r\n    ',
     '\r\n    ',
     '\r\n    ',
     '\r\nTEXT I WANT',
     '\xa0',
     '\r\n...\r\n']
    

    而且您已经知道如何处理该列表。

    【讨论】:

      【解决方案2】:

      @Fazlul 链接到的帖子很有帮助,尽管它缺少我需要的步骤。对于未来有这个问题的人:

      让我感到困惑的是我无法从 Scrapy Selector 对象中删除 html 元素。但是我只需要在选择器上使用 extract() 来获取一个字符串,然后就可以了。

      from w3lib.html import remove_tags, remove_tags_with_content 
      
      posts = response.css('div.contentRow-main')
      for post in posts:
          body = post.css('div.bbWrapper')[0]
          content = remove_tags(remove_tags_with_content(body.extract(), ('blockquote', )))
          item['content'] = content
      

      【讨论】:

        猜你喜欢
        • 2012-08-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-04
        • 2014-06-28
        • 1970-01-01
        • 2014-01-07
        • 1970-01-01
        相关资源
        最近更新 更多