如何在 Scrapy 中使用代理池进行反爬虫?

2023-04-17 00:00:00 爬虫 代理 如何在

在Scrapy中使用代理池进行反爬虫,可以通过在settings.py中配置DOWNLOADER_MIDDLEWARES来实现。以下为详细步骤:

  1. 安装代理池

可以选择自己搭建代理池或使用第三方代理池服务。这里以使用第三方代理池API为例,安利几个比较稳定的代理池服务:

  • 快代理
  • 阿布云
  • 蚂蚁代理

比如,我们可以从快代理购买IP,并通过API来获取可用的代理IP。

  1. 在settings.py中配置代理中间件
DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 543,
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': 550,
    'pidancode.middlewares.ProxyMiddleware': 600,
}

其中,HttpProxyMiddleware是Scrapy自带的代理中间件,用于设置全局代理,而我们需要设置的是动态代理,所以需要自定义实现一个ProxyMiddleware,如下:

import requests
from scrapy import signals
from scrapy.exceptions import NotConfigured


class ProxyMiddleware:
    def __init__(self, proxy_pool_url):
        self.proxy_pool_url = proxy_pool_url

    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        proxy_pool_url = settings.get('PROXY_POOL_URL')
        if not proxy_pool_url:
            raise NotConfigured('PROXY_POOL_URL is not set')
        return cls(proxy_pool_url)

    def process_request(self, request, spider):
        proxy = self.get_proxy()
        request.meta['proxy'] = proxy

    def process_response(self, request, response, spider):
        if response.status == 403:
            proxy = self.get_proxy()
            request.meta['proxy'] = proxy
            return request
        return response

    def get_proxy(self):
        try:
            response = requests.get(self.proxy_pool_url)
            if response.status_code == 200:
                return "http://" + response.text
        except Exception as e:
            raise NotConfigured(e)

在这个中间件中,我们通过get_proxy方法从代理池API中获取可用代理IP,并设置给请求的meta中,然后在之后的请求中,通过HttpProxyMiddleware中间件来动态设置代理IP。

  1. 在spider中使用代理IP

在需要使用代理IP的Spider中,需要在meta中设置好代理IP,详细使用方法如下:

import scrapy


class MySpider(scrapy.Spider):
    name = 'example.com'
    start_urls = ['http://www.example.com']

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(url, meta={
                'proxy': 'http://ip:port',
                'dont_retry': True,
                'download_timeout': 10,
                'handle_httpstatus_list': [403],
            })

    # ...省略其他代码

在这个例子中,我们在start_requests方法中手动设置了代理IP,如果您使用的是第三方代理池服务,则可以不用手动设置。

相关文章