Scrapy框架之 中间件的使用

爬虫中间件

  • 特点 :主要处理蜘蛛(Spider)和下载器(Downloader)之间的请求和响应。可以对蜘蛛生成的请求进行拦截、修改或过滤,也可以对下载器返回给蜘蛛的响应进行处理。
  • 适用场景
    • 请求过滤与修改:当需要根据蜘蛛的某些条件对生成的请求进行过滤或修改时,例如根据蜘蛛的状态、爬取深度等决定是否发送某个请求,或者修改请求的参数、URL 等。
    • 响应处理:对下载器返回的响应进行统一的预处理,比如检查响应的状态码,根据不同的状态码进行不同的处理;或者对响应内容进行初步的清洗、解析,提取一些公共信息供蜘蛛后续使用。
    • 实现分布式爬虫:在分布式爬虫场景中,用于协调不同节点之间的爬取任务,例如根据节点的负载情况分配请求,或者对分布式环境下的请求和响应进行特殊处理,确保爬取任务的高效执行。

下载中间件

  • 特点 :主要作用于下载器层面,用于处理 HTTP 请求和响应。可以在请求发送到服务器之前对请求进行修改,如添加请求头、代理设置等;也可以在响应返回后对响应进行处理,如解压、解码等操作。
  • 适用场景
    • 请求头设置 :像前面提到的随机设置User-Agent,以及添加其他自定义的请求头信息,以伪装请求来源或满足网站的特定要求。
    • 代理设置:当需要使用代理服务器来发送请求时,下载中间件是设置代理的合适位置。可以根据不同的条件动态选择代理服务器,或者对代理的使用进行管理和监控,如处理代理的认证、检测代理的可用性等。
    • 响应处理:对响应进行一些与数据传输和格式相关的处理,例如对压缩的响应进行解压(如处理gzip压缩的响应),对编码后的响应进行解码,确保蜘蛛接收到的是正确格式的响应内容。

在实际的爬虫项目中,通常会同时使用爬虫中间件和下载中间件。下载中间件用于处理与 HTTP 请求和响应相关的底层操作,而爬虫中间件则更侧重于处理与蜘蛛逻辑相关的请求和响应,两者结合可以满足复杂的爬虫需求。例如,在一个爬取电商网站的项目中,可能会使用下载中间件来设置代理和随机User-Agent,以避免被网站封禁;同时使用爬虫中间件来根据商品的分类过滤请求,只爬取特定类别的商品信息,并对响应中的通用信息进行提取和处理。

python 复制代码
DOWNLOADER_MIDDLEWARES = {
    # 其他中间件...
    'your_project_name.middlewares.ProxyMiddleware': 543,
}

543:这是中间件的优先级,数值越小,中间件越先被执行。

代理中间件

python 复制代码
import random
import base64

class ProxyMiddleware:
    def __init__(self):
        self.proxy_list = [
            'http://proxy1.example.com:8080',
            'http://proxy2.example.com:8080',
        ]
        self.username = 'your_username'
        self.password = 'your_password'

    def process_request(self, request, spider):
        proxy = random.choice(self.proxy_list)
        request.meta['proxy'] = proxy
        
		# 添加代理认证信息
        if self.username and self.password:
            auth = f'{self.username}:{self.password}'
            auth_encoded = base64.b64encode(auth.encode('utf-8')).decode('utf-8')
            request.headers['Proxy-Authorization'] = f'Basic {auth_encoded}'

        return None

    def process_exception(self, request, exception, spider):
        # 处理代理失败的情况
        proxy = request.meta.get('proxy')
        if proxy in self.proxy_list:
            self.proxy_list.remove(proxy)
        return request

Scrapy 的下载器中间件中,process_request方法的返回值有特定的含义:

  • return None:这是最常见的返回值。当返回None时,Scrapy 会继续处理这个请求,也就是会将请求发送给下一个中间件(如果有的话),最终由下载器去执行请求操作。
  • return Response:若返回一个Response对象,Scrapy 会停止处理这个请求的后续中间件,并且直接将这个Response对象作为请求的响应返回给蜘蛛(Spider)进行处理。
  • return Request:要是返回一个新的Request对象,Scrapy 会停止处理当前请求,然后将新的Request对象重新加入到请求队列中,等待后续处理。

UserAgent中间件

python 复制代码
class UserAgentMiddleware:
    def process_request(self, request, spider):
        user_agant = random.choice(USER_AGENT_LIST)
        # 添加请求头
        request.headers['User-Agent'] = user_agant
        return None

Selenium中间件

python 复制代码
from DrissionPage import Chromium

class SeleniumMiddleware:
    def __init__(self, crawler):
        self.crawler = crawler
        # 连接 spider_closed 信号和 spider_closed 方法
        self.crawler.signals.connect(self.spider_closed, signal=signals.spider_closed)
        self.browser = Chromium()
        self.tab = self.browser.latest_tab

    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler)

    def process_request(self, request, spider):
        self.tab.get(request.url)
        body = self.tab.html
        return HtmlResponse(url=request.url, body=body, request=request, encoding='utf-8')
       
    def spider_closed(self, spider):
        self.tab.close()
        self.browser.quit()
    
相关推荐
灏瀚星空3 小时前
量化交易之数学与统计学基础2.4——线性代数与矩阵运算 | 矩阵分解
笔记·python·线性代数·信息可视化·矩阵
noedn3 小时前
图像畸变-径向切向畸变实时图像RTSP推流
python·ffmpeg
Kay_Liang4 小时前
探究排序算法的奥秘(下):快速排序、归并排序、堆排序
java·数据结构·c++·python·算法·排序算法
禺垣4 小时前
AdaBoost算法的原理及Python实现
人工智能·python·算法·机器学习·数据挖掘·adaboost·集成学习
带娃的IT创业者5 小时前
《Python Web部署应知应会》Flask网站隐藏或改变浏览器URL:从Nginx反向代理到URL重写技术
前端·python·flask
灏瀚星空6 小时前
量化交易之数学与统计学基础2.3——线性代数与矩阵运算 | 线性方程组
笔记·python·信息可视化·数据挖掘·回归·开源·最小二乘法
素雪风华6 小时前
conda管理python环境
python·conda·pip
Theodore_10226 小时前
Python3(19)数据结构
大数据·开发语言·数据结构·python·网络爬虫
王大傻09286 小时前
python + segno 生成个人二维码
开发语言·python