我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

scrapy目前是非常火热的抓取框架,苏南大叔以前更新过这个scrapy框架的部分教程。目前,对以前的内容进行一些适当的补充。本文中,解决的问题是scrapy抓取文件的时候,会碰到一些非200状态码的情况,比如:500/301/302之类的异常请求。

苏南大叔:scrapy抓取,如何改写非200状态码的response返回值? - scrapy-response-status
scrapy抓取,如何改写非200状态码的response返回值?(图6-1)

大家好,这里是苏南大叔的“程序如此灵动”博客,我是苏南大叔。本文中,苏南大叔将对scrapy碰到的非200情况进行处理。希望对您有所帮助。

本文测试环境:win10python@3.6.8scrapy@2.5.1

新建scrapy项目

这里先回顾一下建立scrapy的方法,scrapy项目是使用pip安装的。

pip install scrapy

苏南大叔:scrapy抓取,如何改写非200状态码的response返回值? - pip-install-scrapy
scrapy抓取,如何改写非200状态码的response返回值?(图6-2)

创建一个新的项目su,新建一个名为example的蜘蛛,目标网站是example.com

scrapy startproject su
cd su
scrapy genspider example example.com

苏南大叔:scrapy抓取,如何改写非200状态码的response返回值? - scrapy项目结构
scrapy抓取,如何改写非200状态码的response返回值?(图6-3)

然后对su/spiders/example.py编写实际的蜘蛛逻辑,并运行编写的蜘蛛代码。

scrapy crawl example

结果发现,在实际的批量数据抓取过程中,一些文章页面会跳转到另外的栏目,提供的并不是苏南大叔的目标数据,导致后续逻辑出错。

解决方案

新建middleware,处理process_response函数,对于非200状态码的情况,模拟一个新的response

su/middlewares.py:

class CheckStatus(object):
    def process_response(self, response, request, spider):
        if response.status != 200:
            # print(response.status)
            return response.replace(body="")
        else:
            return response

su/settings.py:

DOWNLOADER_MIDDLEWARES = {
    'su.middlewares.CheckStatus': 542,
}

这里的su.middlewares.CheckStatus是有命名依据的,是上述捕获非200代码处理方案的class的名字。542只是一个比较大的值,用于控制权重的。所以,您可以修改为您喜欢的任何合理数字。

spiders/example.py里面不做任何的逻辑修改,当然,值得注意的是,当出现非200的情况时,获得的html是自己可以自定义的。上述代码里面是留空了,实际上可以替换成任何想自定义的标记。

苏南大叔:scrapy抓取,如何改写非200状态码的response返回值? - scrapy-middleware-response
scrapy抓取,如何改写非200状态码的response返回值?(图6-4)

可能的问题一

middleware里面,如果直接修改responsebody

response.body=""

会得到一个错误提示:

AttributeError: HtmlResponse.body is not modifiable, use HtmlResponse.replace() instead

这里的解决方案就是使用response.replace(),这里不但可以替换body,实际上还可以替换status,url等等。这里大家可以自行试验。

response.replace(body="")

苏南大叔:scrapy抓取,如何改写非200状态码的response返回值? - middleware
scrapy抓取,如何改写非200状态码的response返回值?(图6-5)

可能的问题二

不要以为上述middleware可以捕获所有的状态码了,您还可能会碰到如下类似提示信息:

Ignoring response <500>: HTTP status code is not handled or not allowed

解决方案是,修改settings.py

HTTPERROR_ALLOWED_CODES = [403,500]

当然需要您根据实际情况,修改上述数组,添加新的错误状态码。如果不做上述修改的话,scrapy运行时如果碰到500状态返回值,可能会意外结束运行。

苏南大叔:scrapy抓取,如何改写非200状态码的response返回值? - settings
scrapy抓取,如何改写非200状态码的response返回值?(图6-6)

相关链接

总结

scrapy爬虫似乎很好很强大,不过对于苏南大叔来说,还是比较喜欢使用php外加phpquery来直接写,似乎思路会更加流畅。但是,拥抱新技术才是正确的选择。更多scrapy的经验文字,请点击苏南大叔的博客:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   python    scrapy