首页 > 解决方案 > 如何从 Scrapy Selector 中删除子元素?

问题描述

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

我尝试使用 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>

标签: pythonweb-scrapingscrapy

解决方案


首先,在您给出的示例中,如果我只选择 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']

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


推荐阅读