如何从 Scrapy 选择器中删除子元素?

How do you delete a subelement from a Scrapy Selector?

我正在尝试使用 Scrapy 抓取某些论坛 post 的内容,我想排除引用自之前 post 的文本。我很幸运,该网站非常清楚地标记了这段引用的文本(它在“blockquote”标签内),但我不知道如何获取所有 not 中的文本块引用标记。下面是论坛 post 结构的示例。在这个特定的 post 中,用户写了一些东西,然后引用了前面的 post,然后又写了一些。所以基本上,我想要删除的标签夹在我想要的内容之间。更常见的是,引用的文本在前面,新的文本在后面,但我也需要能够处理这种奇怪的情况。

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

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

或者更好不要select它(搜索所有div没有div的标签class="bbCodeBlock-title" 祖先或自己):

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']

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

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

让我感到困惑的是我无法从 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