scrapy爬虫框架之middlewares(中间件)与settings配置文件

Downloader Middleware

下载中间件是一个钩子到Scrapy的请求/响应处理的框架。这是一个轻量级的、低级的系统,用于全局改变Scrapy的请求和响应。

激活下载器中间件

settings.py配置,这是一个dict,键是中间件类路径,值是中间件顺序。

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.CustomDownloaderMiddleware': 543,
}

下载器中间件顺序

DOWNLOADER_MIDDLEWARES 与DOWNLOADER_MIDDLEWARES_BASE(猜测是内置中间件)不存在覆盖关系,而是按顺序排序,以获得已启用中间件的最终排序列表:第一个中间件更接近引擎,最后一个更接近下载程序。也就是说, process_request() 每个中间件的方法将以增加的中间件顺序(100、200、300…)调用,并且 process_response() 每个中间件的方法将按降序调用。

禁用内置中间件

如果要禁用内置中间件(定义于 DOWNLOADER_MIDDLEWARES_BASE 在默认情况下启用)您必须在项目的 DOWNLOADER_MIDDLEWARES 设置和分配 None 作为其价值。例如,如果要禁用用户代理中间件:

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.CustomDownloaderMiddleware': 543,
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
}

编写自己的下载器中间件

每个下载器中间件都是一个python类,它定义了下面定义的一个或多个方法。

主要入口点是from_crawler类方法,它接收 Crawler 实例。

class scrapy.downloadermiddlewares.DownloaderMiddleware

注意:任何下载器中间件方法也可能返回延迟。

process_request(request, spider)

param
request (Request object) – 正在处理的请求
spider (Spider object) – 此请求所针对的爬虫

对于通过下载中间件的每个请求调用此方法。

process_request()返回值

  1. None,scrapy将继续处理此请求,执行所有其他中间软件,直到最后调用适当的下载器处理程序执行请求(及其下载的响应)。
  2. 返回一个response对象,scrapy不用调用任何其他 process_request() 或 process_exception() 方法或适当的下载函数;它将返回该响应。这个 process_response() 每次响应都会调用已安装中间件的方法。
  3. 返回一个request对象,Scrapy将停止调用process_request方法,并重新调度返回的请求。一旦执行了新返回的请求,将对下载的响应调用适当的中间件链。
  4. 触发IgnoreRequest异常, process_exception() 将调用已安装的下载器中间件的方法。如果它们都不处理异常,则请求的errback函数 (Request.errback )。如果没有代码处理引发的异常,则忽略该异常,不记录该异常(与其他异常不同)。

process_response(request, response, spider)

param
request (is a Request object) – 发起响应的请求
response (Response object) – 正在处理的响应
spider (Spider object) – 此响应所针对的爬虫

process_response() 返回值

  1. 返回一个 Response 对象,(可能是相同的给定响应,也可能是全新的响应),响应将继续使用 process_response() 链中的下一个中间件。
  2. 返回一个 Request 对象,间件链将暂停,返回的请求将重新计划为将来下载。这与从返回请求的行为相同 process_request() 。
  3. 触发 IgnoreRequest IgnoreRequest 异常,请求的errback函数 (Request.errback )。如果没有代码处理引发的异常,则忽略该异常,不记录该异常(与其他异常不同)。

process_exception(request, exception, spider)

param
request (is a Request object) – 生成异常的请求
exception (an Exception object) – 引发的异常
spider (Spider object) – 此请求所针对的爬虫

process_exception() 当下载处理程序或 process_request() (从下载器中间件)引发异常(包括 IgnoreRequest)

process_exception()返回值:

  1. None,Scrapy将继续处理此异常,执行任何其他 process_exception() 安装的中间件的方法,直到没有中间件,默认的异常处理开始。
  2. 一个Response 对象,如果它返回 Response 对象 process_response() 已安装中间件的方法链已启动,Scrapy不需要调用任何其他方法。
  3. 一个 Request 对象,如果它返回一个 Request 对象,则返回的请求将被重新安排为将来下载。这会停止执行 process_exception() 中间件的方法与返回响应相同。

from_crawler(cls, crawler)

如果存在,则调用该类方法从 Crawler . 它必须返回中间件的新实例。爬虫对象提供对所有零碎核心组件(如设置和信号)的访问;它是中间件访问它们并将其功能连接到零碎的一种方式。

参数
crawler (Crawler object) – 使用此中间件的爬虫程序

遗留问题

总结中间件最初的原因是因为我要测试爬虫的超时,想在中间件sleep造成假超时的状态,但超时问题想到了另一种办法来解决,在settings中把DOWNLOAD_TIMEOUT设置为很小,爬虫自然会超时了。

scrapy中间件并没有总结完,暂时用不着,以后再说吧

settings配置文件

#-----------------------项目结构配置----------------
BOT_NAME = 'xigua'    # Scrapy项目的名字,这将用来构造默认 User-Agent,同时也用来log,当您使用 startproject 命令创建项目时其也被自动赋值。
SPIDER_MODULES = ['xigua.spiders']  #Scrapy搜索spider的模块列表 默认: [xxx.spiders],如果爬虫有多个文件夹的话,可以后边跟着写上
NEWSPIDER_MODULE = 'xigua.spiders'  #使用 genspider 命令创建新spider的模块。默认: 'xxx.spiders'



#-----------------------日志文件配置-----------------------------------
# 默认: True,是否启用logging。
LOG_ENABLED=True
# 默认: 'utf-8',logging使用的编码。
LOG_ENCODING='utf-8'
# 它是利用它的日志信息可以被格式化的字符串。默认值:'%(asctime)s [%(name)s] %(levelname)s: %(message)s'
LOG_FORMAT='%(asctime)s [%(name)s] %(levelname)s: %(message)s'
# 它是利用它的日期/时间可以格式化字符串。默认值: '%Y-%m-%d %H:%M:%S'
LOG_DATEFORMAT='%Y-%m-%d %H:%M:%S'
#日志文件名
LOG_FILE = "dg.log"
#日志文件级别,默认值:“DEBUG”,log的最低级别。可选的级别有: CRITICAL、 ERROR、WARNING、INFO、DEBUG 。
LOG_LEVEL = 'WARNING'



#-----------request并发、超时、重试等----------------
# 对于失败的HTTP请求(如超时)进行重试会降低爬取效率,当爬取目标基数很大时,舍弃部分数据不影响大局,提高效率
RETRY_ENABLED = False

#请求下载超时时间,默认180秒
DOWNLOAD_TIMEOUT=20

# 这是响应的下载器下载的最大尺寸,默认值:1073741824 (1024MB)
DOWNLOAD_MAXSIZE=1073741824
# 它定义为响应下载警告的大小,默认值:33554432 (32MB)
DOWNLOAD_WARNSIZE=33554432

# 它定义了将被允许抓取的网址的长度为URL的最大极限,默认值:2083
URLLENGTH_LIMIT = 5000


# 并发请求,默认16
CONCURRENT_REQUESTS = 32
# 对单个网站进行并发请求的最大值
CONCURRENT_REQUESTS_PER_DOMAIN = 16  
# 对单个ip进行并发请求的最大值,并发限制将针对IP,而不是网站。该设定也影响 DOWNLOAD_DELAY: 如CONCURRENT_REQUESTS_PER_IP 非0,下载延迟应用在IP而不是网站上。
CONCURRENT_REQUESTS_PER_IP = 16
# 默认每个域名的并发数:8
CONCURRENT_REQUESTS_PER_DOMAIN = 16
# 默认 Item 并发数:100
CONCURRENT_ITEMS = 100

# 下载器延迟时间,下载器在同一网站面前需要等待的时间,
# 该选项可以用来限制爬取速度,减轻服务器压力。同时也支持小数:0.25 以秒为单位
# 下载延迟设置,只能有一个生效
# DOWNLOAD_DELAY 会影响 CONCURRENT_REQUESTS,不能使并发显现出来,设置下载延迟
DOWNLOAD_DELAY = 3


#--------------request参数-------------------
# 禁用cookie(默认情况下启用)
COOKIES_ENABLED = False
COOKIES_DEBUG = True

# 它定义了在抓取网站所使用的用户代理,默认值:“Scrapy / VERSION“
USER_AGENT = 'xigua (+http://www.yourdomain.com)'

# 覆盖默认请求标头,也可以加入请求头,获取同样来自开发着工具,
# 很多网站都会检查客户端的headers,比如豆瓣就是每一个请求都检查headers的user_agent,否则只会返回403,可以开启USER_AGENT 请求头
DEFAULT_REQUEST_HEADERS = {
   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
   'Accept-Language': 'en',
}





#-----------中间件-----------------------
# 启用或禁用蜘蛛中间件
SPIDER_MIDDLEWARES = {
    'companyNews.middlewares.UserAgentmiddleware': 401,
    'companyNews.middlewares.ProxyMiddleware':426,
}
# 启用或禁用下载器中间件
DOWNLOADER_MIDDLEWARES = {
    'companyNews.middlewares.UserAgentmiddleware': 400,
    'companyNews.middlewares.ProxyMiddleware':425,
    # 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware':423,
     # 'companyNews.middlewares.CookieMiddleware': 700,
}
MYEXT_ENABLED=True      # 开启扩展
IDLE_NUMBER=12           # 配置空闲持续时间单位为 360个 ,一个时间单位为5s
# 在 EXTENSIONS 配置,激活扩展
EXTENSIONS = {
    # 'scrapy.extensions.telnet.TelnetConsole': None,
    'companyNews.extensions.RedisSpiderSmartIdleClosedExensions': 500,
}
# 配置项目管道,如下载图片的图片管道,分布式爬虫多爬虫的pipeline,结尾int值是优先级,可以理解为权重,以逗号间隔,是个集合
# 注意:自定义pipeline的优先级需高于Redispipeline,因为RedisPipeline不会返回item,
# 所以如果RedisPipeline优先级高于自定义pipeline,那么自定义pipeline无法获取到item
ITEM_PIPELINES = {
     #将清除的项目在redis进行处理,# 将RedisPipeline注册到pipeline组件中(这样才能将数据存入Redis)
    # 'scrapy_redis.pipelines.RedisPipeline': 400,
    'companyNews.pipelines.companyNewsPipeline': 300,# 自定义pipeline视情况选择性注册(可选)
}



# ----------------scrapy默认已经自带了缓存,配置如下-----------------
# 打开缓存
HTTPCACHE_ENABLED = True
# 设置缓存过期时间(单位:秒)
HTTPCACHE_EXPIRATION_SECS = 0
# 缓存路径(默认为:.scrapy/httpcache)
HTTPCACHE_DIR = 'httpcache'
# 忽略的状态码
HTTPCACHE_IGNORE_HTTP_CODES = []
HTTPERROR_ALLOWED_CODES = [302, 301]
# 缓存模式(文件缓存)
HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'








#-----------------Scrapy-Redis分布式爬虫相关设置如下--------------------------
#启用Redis调度存储请求队列,使用Scrapy-Redis的调度器,不再使用scrapy的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

#确保所有的爬虫通过Redis去重,使用Scrapy-Redis的去重组件,不再使用scrapy的去重组件
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

# 默认请求序列化使用的是pickle 但是我们可以更改为其他类似的。PS:这玩意儿2.X的可以用。3.X的不能用
SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat"

# 使用优先级调度请求队列 (默认使用),
# 使用Scrapy-Redis的从请求集合中取出请求的方式,三种方式择其一即可:
# 分别按(1)请求的优先级/(2)队列FIFO/(先进先出)(3)栈FILO 取出请求(先进后出)
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'
# 可选用的其它队列
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue'

#不清除Redis队列、这样可以暂停/恢复 爬取,
# 允许暂停,redis请求记录不会丢失(重启爬虫不会重头爬取已爬过的页面)
SCHEDULER_PERSIST = True



#----------------------redis的地址配置-------------------------------------

# 指定用于连接redis的URL(可选)
# 如果设置此项,则此项优先级高于设置的REDIS_HOST 和 REDIS_PORT
REDIS_URL = 'redis://root:密码@主机IP:端口'
REDIS_URL = 'redis://root:[email protected]:6379'
REDIS_URL = 'redis://root:%s@%s:%s'%(password_redis,host_redis,port_redis)
# 自定义的redis参数(连接超时之类的)
REDIS_PARAMS={'db': db_redis}

# 指定连接到redis时使用的端口和地址(可选)
REDIS_HOST = '127.0.0.1'
REDIS_PORT = 6379
REDIS_PASS = '19940225'







#---------------其他-----------------------
# 每个网站都会有一个robots.txt,上面规定了哪些地址是不可以被爬取的,但实际上网站所有地址均不允许被爬取
# 如果启用,Scrapy将会采用 robots.txt策略,常使用不遵循Flase
ROBOTSTXT_OBEY = False

# 禁用Telent控制台(默认启用)
TELNETCONSOLE_ENABLED = False

# 爬取网站最大允许的深度(depth)值,默认值0。如果为0,则没有限制
DEPTH_LIMIT = 3
# 整数值。用于根据深度调整request优先级。如果为0,则不根据深度进行优先级调整。
DEPTH_PRIORITY=3

# 最大空闲时间防止分布式爬虫因为等待而关闭
# 这只有当上面设置的队列类是SpiderQueue或SpiderStack时才有效
# 并且当您的蜘蛛首次启动时,也可能会阻止同一时间启动(由于队列为空)
SCHEDULER_IDLE_BEFORE_CLOSE = 10

# 序列化项目管道作为redis Key存储
REDIS_ITEMS_KEY = '%(spider)s:items'

# 默认使用ScrapyJSONEncoder进行项目序列化
REDIS_ITEMS_SERIALIZER = 'json.dumps'

# 自定义redis客户端类
REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient'

# 如果为True,则使用redis的'spop'进行操作。
# 如果需要避免起始网址列表出现重复,这个选项非常有用。开启此选项urls必须通过sadd添加,否则会出现类型错误。
REDIS_START_URLS_AS_SET = False

# RedisSpider和RedisCrawlSpider默认 start_usls 键
REDIS_START_URLS_KEY = '%(name)s:start_urls'

# 设置redis使用utf-8之外的编码
REDIS_ENCODING = 'latin1'

# 开始下载时限速并延迟时间
AUTOTHROTTLE_START_DELAY = 5

# 高并发请求时最大延迟时间
AUTOTHROTTLE_MAX_DELAY = 60

# Scrapy请求的平均数量应该并行发送每个远程服务器
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0

# 启用显示所收到的每个响应的调节统计信息
AUTOTHROTTLE_DEBUG = False

# 值为0即为不启用
# 爬取指定时间关闭爬虫
CLOSESPIDER_TIMEOUT = 0
# 爬取指定数量页面关闭爬虫
CLOSESPIDER_PAGECOUNT = 0
# 爬取指定数量item关闭爬虫
CLOSESPIDER_ITEMCOUNT = 0
# 爬取指定数量错误关闭爬虫
CLOSESPIDER_ERRORCOUNT = 0

最后再来两条启用调试的命令:

启用调试工具
命令行调试
scrapy shell url 查看网页,不过这种方式可能对于要请求头的网页不行,对于一般的网页还是可以的
scrapy view shell 用来查看动态加载的网页,如果查看的网页用了动态加载,那么用这个命令行打开的网页就是不完整的,肯定缺少了什么

暂停和恢复爬虫
初学者最头疼的事情就是没有处理好异常,当爬虫爬到一半的时候突然因为错误而中断了,但是这时又不能从中断的地方开始继续爬,顿时感觉心里日了狗,但是这里有一个方法可以暂时的存储你爬的状态,当爬虫中断的时候继续打开后依然可以从中断的地方爬,不过虽说持久化可以有效的处理,但是要注意的是当使用cookie临时的模拟登录状态的时候要注意cookie的有效期

只需要在setting.py中JOB_DIR=file_name 其中填的是你的文件目录,注意这里的目录不允许共享,只能存储单独的一个spdire的运行状态,如果你不想在从中断的地方开始运行,只需要将这个文件夹删除即可

当然还有其他的放法:scrapy crawl somespider -s JOBDIR=crawls/somespider-1,这个是在终端启动爬虫的时候调用的,可以通过ctr+c中断,恢复还是输入上面的命令

部分内容转载自:
https://docs.scrapy.org/en/latest/search.html?q=hasattr%28failure.value&check_keywords=yes&area=default#

https://www.osgeo.cn/scrapy/search.html?q=hasattr&check_keywords=yes&area=default#
https://www.cnblogs.com/canhun/p/11124247.html

你可能感兴趣的:(爬虫,中间件,scrapy,爬虫)