如何从 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"> </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
我正在尝试使用 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"> </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