«

scrapy中间件的使用

时间:2023-3-1 18:55     作者:wen     分类: Python


一、scrapy中间件的分类和作用

  1. scrapy中间件的分类
    根据scrapy运行流程中所在位置不同分为

    1. 下载中间件
    2. 爬虫中间件
  2. scrapy中间件的作用:预处理request和response对象

    1. 对header以及cookie进行跟换和处理
    2. 使用代理ip等
    3. 对请求进行定制化操作

但是scrapy默认的情况下,两种中间件都在middlewares.py一个文件中
爬虫中间件使用方法和下载中间件相同,且功能重复,通常使用下载中间件

二、下载中间件的使用方法:

  1. 在middlewares.py中定义中间件
  2. 在中间件类中,重写处理请求或响应的方法

Download Middlewares默认方法:
process_request(self, request, spider):

  1. 当每个request通过下载中间件时,该方法被调用
  2. 返回None值:没有return也是返回None,该request对象传递给下载器,或通过引擎传递给其它权重低的process_request方法
  3. 返回Response对象:不再请求,把response返回给引擎
  4. 返回Request对象:把request对象通过引擎交给调度器,此时将不通过其它权重低的process_request方法

process_response(self, request, response, spider):

  1. 当下载器完成http请求,传递响应给引擎的时候调用

  2. 返回Response:通过引擎交给爬虫处理或交给权重更低的其它下载中间件的process_response方法

  3. 返回Request对象:通过引擎交给调度器继续请求,此时将不通过其它权重的process_request方法

  4. 在setting.py中配置开启中间件,权重值越小越优先执行

# Enable or disable spider middlewares
# See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
#SPIDER_MIDDLEWARES = {
#    'tencent.middlewares.TencentSpiderMiddleware': 543,
#}

# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
DOWNLOADER_MIDDLEWARES = {
   'tencent.middlewares.TencentDownloaderMiddleware': 543,
}

三、定义实现随机User-Agent的下载中间件

1、在middlewares.py中完善代码

# middlewares.py
# 定义一个中间件
class RandomUserAgent:
    def process_request(self, request, spider):
        print(request.headers['User-Agent'])

        ua = random.choice(USER_AGENT_LIST)
        request.headers['User-Agent'] = ua

2、在setting中设置开启自定义的下载中间件,设置方法同管道

# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
DOWNLOADER_MIDDLEWARES = {
   'douban.middlewares.DoubanDownloaderMiddleware': 543,
   'douban.middlewares.RandomUserAgent': 544,
}

3、在setting中添加UA的列表

# setting.py
USER_AGENT_LIST = [
   'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36',
   'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:65.0) Gecko/20100101 Firefox/65.0',
   'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15',
   'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36',
   'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763',
   'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko'
]

四、代理IP的使用

  1. 思路分析

    1. 代理添加的位置:request.meta中添加proxy字段
    2. 获取一个代理IP,赋值给request.meta['proxy']
      • 代理池中随机选择代理ip
      • 代理IP的webapi发送请求获取一个代理ip
  2. 具体实现

# middlewares.py
class RandomProxy:
    def process_request(self, request, spider):
        proxy = random.choice(PROXY_LIST)
        print(proxy)
        if 'user_passwd' in proxy:
            # 对账号密码进行编码
            b64_up = base64.b64encode(proxy['user_passwd'].encode())
            # 设置认证
            request.headers['Proxy-Authorization'] = 'Basic ' + b64_up.decode()
            # 设置代理
            request.meta['proxy'] = proxy['ip_prot']
        else:
            # 设置代理
            request.meta['proxy'] = proxy['ip_prot']
# setting.py
PROXY_LIST = [
    {'ip_prot': "115.218.5.127:9000"},
    {'ip_prot': "183.21.81.88:40539"},
]
  1. 检测代理ip是否可用
    在使用代理IP的情况下可以在下载中间件的process_response()方法中处理代理的使用情况,如果该代理ip不能使用可以替换其它代理ip

    # middlewares.py
    class RandomProxy:
    def process_request(self, request, spider):
        proxy = random.choice(PROXY_LIST)
        print(proxy)
        if 'user_passwd' in proxy:
            # 对账号密码进行编码
            b64_up = base64.b64encode(proxy['user_passwd'].encode())
            # 设置认证
            request.headers['Proxy-Authorization'] = 'Basic ' + b64_up.decode()
            # 设置代理
            request.meta['proxy'] = proxy['ip_prot']
        else:
            # 设置代理
            request.meta['proxy'] = proxy['ip_prot']
    
    def process_response(self, request, response, spider):
        if response.status != 200:
            request.dont_filter = True  # 重新发送的请求对象能够再次进入列队
            return request

    在setting中开启下载器中间件

五、在中间件中使用selenium

1、完成爬虫代理

# middlewares.py
class Selenium:
    def process_request(self, request, spider):
        url = request.url
        if 'daydata' in url:
            driver = webdriver.Chrome()
            driver.get(url)
            time.sleep(3)
            data = driver.page_source
            driver.close()

            # 创建响应对象
            res = HtmlResponse(url=url,body=data,encoding='utf-8',request=request)
            return res

标签: 爬虫