跳转到内容
Guides 2 分钟阅读 1410 次浏览

Scrapy 代理配置

为 Scrapy 配置代理中间件,实现高效的网页抓取。轮换代理以避免 IP 封禁并保持匿名。马上学习配置方法!

Python Parsing
Scrapy 代理配置

HTTP 代理服务器充当您的网页抓取脚本与目标网站之间的中介。Scrapy 爬虫不再直接连接目标,而是先连接到代理服务器,再由代理把请求转发给目标。这样您就可以隐藏自己的 IP 地址、绕过地域限制,并避免被采用反抓取措施的网站封禁。本文提供一份使用 Scrapy 中间件配置和轮换代理的实用指南。

使用中间件在 Scrapy 中配置代理

Scrapy 的中间件系统提供了处理请求和响应的灵活方式。我们可以利用这套系统来实现代理支持。整个过程就是创建一个自定义中间件,拦截请求并为其分配代理服务器。

创建自定义代理中间件

首先,在您的 Scrapy 项目中新建一个 Python 文件(例如 proxy_middleware.py)。该文件将包含自定义代理中间件的代码。

import random

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

    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler.settings.getlist('PROXIES'))

    def process_request(self, request, spider):
        proxy = random.choice(self.proxies)
        request.meta['proxy'] = proxy
        print(f"Using proxy: {proxy}")

    def process_response(self, request, response, spider):
         # 可选:处理响应状态码,以便换用其他代理重试
        if response.status in [403, 429]:
            print(f"Proxy {request.meta['proxy']} blocked, retrying with another proxy.")
            return self._retry_request(request, spider)
        return response

    def _retry_request(self, request, spider):
        proxy = random.choice(self.proxies)
        request.meta['proxy'] = proxy
        new_request = request.copy()
        return new_request

说明:

  • __init__(self, proxies) 构造函数接收一个代理列表作为输入。
  • from_crawler(cls, crawler) Scrapy 使用这个类方法创建中间件实例。它从 Scrapy 设置中获取代理列表。
  • process_request(self, request, spider) 该方法在 Scrapy 发送请求之前被调用。它从列表中随机选择一个代理,并赋值给请求的 meta['proxy'] 属性,从而告诉 Scrapy 本次请求使用指定的代理。
  • process_response(self, request, response, spider) 该方法让您可以处理服务器返回的响应。这里会检查 403(Forbidden)或 429(Too Many Requests)等状态码,它们通常表示代理已被封禁。若发现封禁状态码,就换一个代理重试该请求。
  • _retry_request(self, request, spider) 该方法创建一个分配了不同代理的新请求。

配置 Scrapy 设置

接下来,您需要配置 Scrapy 设置以启用中间件并提供代理列表。打开 settings.py 文件并添加以下内容:

# settings.py

# 启用 ProxyMiddleware
DOWNLOADER_MIDDLEWARES = {
    'your_project_name.proxy_middleware.ProxyMiddleware': 350,  # 按需调整优先级
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': None, # 禁用默认的 HttpProxyMiddleware
}

# 代理列表
PROXIES = [
    'http://user1:[email protected]:8080',
    'http://user2:[email protected]:8080',
    'http://user3:[email protected]:8080',
    'https://user4:[email protected]:8080',
]

# 代理经常失败,因此多重试几次
RETRY_TIMES = 10

# 代理失败率很高,因此对大多数错误码都重试
RETRY_HTTP_CODES = [500, 502, 503, 504, 400, 408]

# 禁用默认的 user agent 中间件,改用自定义中间件
DOWNLOADER_MIDDLEWARES.update({
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
    'scrapy_user_agents.middlewares.RandomUserAgentMiddleware': 400,
})

# 遵守 robots.txt 规则
ROBOTSTXT_OBEY = False

说明:

  • DOWNLOADER_MIDDLEWARES 这个字典用于启用和配置下载器中间件。键是中间件类的路径,值是中间件的优先级。数字越小优先级越高(中间件越早执行)。为避免与自定义中间件冲突,默认的 HttpProxyMiddleware 被禁用。
  • PROXIES 该列表包含您想使用的代理服务器。格式为 protocol://user:password@host:port。HTTP 和 HTTPS 代理都可以使用。 如果不需要用户名和密码,格式就简化为 protocol://host:port
  • RETRY_TIMESRETRY_HTTP_CODES 这些设置用于配置 Scrapy 的重试中间件。 由于代理可能不稳定,建议增加重试次数,并把可能表示代理问题的常见 HTTP 错误码包含进来。
  • DOWNLOADER_MIDDLEWARES.update(...) 这一段禁用默认的 User Agent 中间件,并启用 scrapy_user_agents 来轮换 User Agent,有助于避免您的抓取器被轻易识别。您需要用 pip install scrapy-user-agents 安装 scrapy_user_agents

运行爬虫

现在您可以像往常一样运行 Scrapy 爬虫。中间件会自动为每个请求分配一个代理。

scrapy crawl your_spider_name

代理轮换策略

轮换代理对于防止抓取器被封禁至关重要。以下是几种常见策略:

  • 随机选择: 如上面的示例所示,为每个请求从列表中随机选择一个代理。这是最简单的方法,但未必最有效。
  • 顺序轮换: 按顺序循环使用代理列表。如果您希望每个代理被使用的次数相同,这种方式很有用。
  • 智能轮换: 实现追踪各个代理表现的逻辑,并优先使用状态良好的代理。这可能涉及监控响应时间、错误率和其他指标。
  • 使用代理 API: 使用能自动处理代理轮换与管理的代理服务 API。这类服务通常提供地理定位和 IP 地址信誉管理等功能。

顺序代理轮换

下面是在中间件中实现顺序代理轮换的示例:

import itertools

class SequentialProxyMiddleware:
    def __init__(self, proxies):
        self.proxies = itertools.cycle(proxies) # 使用 cycle 轮换代理

    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler.settings.getlist('PROXIES'))

    def process_request(self, request, spider):
        proxy = next(self.proxies) # 从循环中取出下一个代理
        request.meta['proxy'] = proxy
        print(f"Using proxy: {proxy}")

    def process_response(self, request, response, spider):
        if response.status in [403, 429]:
            print(f"Proxy {request.meta['proxy']} blocked, rotating to the next proxy.")
            return self._retry_request(request, spider)
        return response

    def _retry_request(self, request, spider):
        proxy = next(self.proxies)
        request.meta['proxy'] = proxy
        new_request = request.copy()
        return new_request

关键变化:

  • itertools.cycle(proxies) 它会创建一个在代理列表上无限循环的迭代器。 使用 next() 函数取出序列中的下一个代理。

请记得把 DOWNLOADER_MIDDLEWARES 设置更新为指向 SequentialProxyMiddleware

代理 API 集成

与代理 API 集成通常意味着向 API 发送请求以获取代理,并处理 API 的认证与错误响应。 具体做法取决于您选择的 API。 许多代理提供商提供 Python SDK 来简化这一过程。

代理类型

不同代理类型的对比如下:

特性 HTTP 代理 HTTPS 代理 SOCKS 代理
协议 HTTP HTTPS SOCKS(多个版本)
加密 客户端与代理之间不加密 客户端与代理之间加密 加密取决于 SOCKS 版本
适用场景 网页浏览、抓取 HTTP 站点 网页浏览、抓取 HTTPS 站点 通用,支持多种协议
匿名性 匿名性可能较低 匿名性可能较高 可以达到很高的匿名性
配置方式 通常在浏览器中配置 通常在浏览器中配置 需要 SOCKS 客户端或库支持
示例 URL http://host:port https://host:port socks5://host:portsocks4://host:port
认证 基本认证(用户名/密码) 基本认证(用户名/密码) 支持用户名/密码认证

常见问题与排查

  • 代理不可用: 确认代理服务器在线且可访问。检查代理的认证凭据(用户名和密码)。确保 settings.py 中的代理格式正确。
  • 代理被封: 实施代理轮换,并考虑使用拥有大量 IP 地址池的代理服务。监控响应码(403、429),并自动换用其他代理重试请求。
  • 性能缓慢: 选择地理位置靠近目标服务器的代理。 测试不同的代理提供商,找到性能可靠的一家。
  • HTTPS 错误: 确保您的代理支持 HTTPS 连接。 有些 HTTP 代理只支持 HTTP 流量。
  • DNS 泄漏: 使用 SOCKS 代理,或把系统配置为使用代理的 DNS 服务器,以防止 DNS 泄漏。

结论

在 Scrapy 中配置和轮换代理,是构建健壮可靠的网页抓取器的关键。通过使用自定义中间件、实施有效的轮换策略并理解不同的代理类型,您可以显著降低被封禁的风险,并提升抓取项目的性能。请持续监控代理,并根据需要调整策略,以保持最佳的抓取效率。

请记得定期测试代理并监控其性能,以确保抓取器持续有效运行。如需更高级的功能和更省心的管理,可以考虑使用代理管理服务。

已更新: 19.05.2026
返回分类

试用我们的代理

遍布 100+ 国家的 20,000+ 代理

support_agent
GProxy Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.