截至2026年10月7日,Shifter拥有规模最大的美国实时IP池,超过Oxylabs和Bright Data,而成本只是其一小部分。Shifter 现在拥有数量最多的美国活跃 IP 资源池

查看基准测试

内置代理管理的爬虫框架:各自能处理什么

对比 Scrapy、Crawlee、Colly、Playwright、Puppeteer 和 Selenium 在代理支持方面的表现:轮换、会话与凭证,以及轮换网关能带来哪些改变。

工程 · 更新于2026年11月9日 · 2分钟阅读
设置轮换会话CrawleeScrapyCollyPlaywrightPuppeteerSelenium
六种工具,三项代理任务。蓝色单元格已为您处理好。
知识
本页内容
  1. 简短的答案
  2. Crawlee:把代理当作受管理的资源
  3. Scrapy:每个请求一个代理,轮换由你负责
  4. Colly:简单的轮询切换器
  5. Playwright 和 Puppeteer:按上下文隔离
  6. Selenium:全浏览器范围,处理密码时较为笨拙
  7. 轮换网关带来的变化
  8. 接入方式
  9. 如何选择
  10. 来源与参考资料

几乎所有爬虫框架都能让你设置代理。能替你管理代理的框架则少得多:自动轮换代理、淘汰被封禁的代理、让某个会话保持在同一个 IP 上。如果你使用住宅代理,弄清楚哪部分工作由框架负责、哪部分由网关负责,可以省下大量胶水代码。

本指南从三个问题出发,比较了六种常见工具:如何设置代理、该工具是否会自行轮换代理、以及它是否会把某个会话绑定到一个代理上。然后展示了在一个轮换网关背后,每种工具所需的少量代码。

简短的答案

工具语言如何设置代理是否自行轮换是否把会话绑定到代理
CrawleeNode.jsProxyConfiguration是:轮询、自定义函数、分层是,通过其会话池
ScrapyPythonrequest.meta["proxy"] 或环境变量否,需要自己写中间件否
CollyGoSetProxy 或 SetProxyFunc是:轮询切换器否
PlaywrightNode.js、Python、Java、.NET启动时或按浏览器上下文设置否按上下文
PuppeteerNode.js启动参数或按浏览器上下文设置否按上下文
Selenium多种全浏览器范围的选项否否

Crawlee 是唯一一个把代理当作需要管理的资源,而不只是一个设置项来处理的工具。浏览器类工具提供了按上下文隔离的能力,这正是实现会话的基础构件,但轮换逻辑需要你自己实现。

Crawlee:把代理当作受管理的资源

Crawlee 的 ProxyConfiguration 接受一个代理 URL 列表,并”以轮询方式”在其中循环使用。除了列表之外,你也可以传入一个函数,由它为每个请求挑选代理。第三种模式是分层代理,它从最便宜的层级开始(通常根本不用代理),当某个站点封锁爬虫时就升到上一层,当较低层级重新可用时再降回去。

最重要的部分是会话。当爬虫运行其会话池时,每个会话都会保持同一个代理:用文档的话说,之后带有相同 sessionId 的调用”将始终返回相同的 proxyUrl”。当 Crawlee 判定某个会话已被封锁时,它会淘汰该会话,下一个会话会拿到一个不同的代理。Cookie 会跟随会话走,所以 IP 和 Cookie 始终保持一致。

Scrapy:每个请求一个代理,轮换由你负责

Scrapy 的 HttpProxyMiddleware 从 request.meta["proxy"] 读取代理,如果没有则回退读取 http_proxy 和 https_proxy 环境变量。凭证可以放在 URL 中,如 http://username:password@host:port。它所做的仅此而已。为每个请求挑选不同的代理、发现封禁并让失效代理休息,这些都要由你自己完成,或者借助诸如 scrapy-rotating-proxies 这样的扩展,它会读取一个代理列表,并默认把非 200 或空响应视为封禁。

我们的 Scrapy 集成指南介绍了基本设置,而在 Scrapy 中轮换住宅代理这篇文章则更深入地讲解了中间件的写法。

Colly:简单的轮询切换器

Go 语言框架 Colly 提供了 SetProxy 用于设置单个代理,以及 SetProxyFunc 用于传入一个为每个请求选择代理的函数。它的 proxy 包中包含 RoundRobinProxySwitcher,该函数会”在每次请求时轮换 ProxyURL”,并支持 http、https 和 socks5 的 URL。这里没有会话的概念:如果两个请求必须共享同一个 IP,需要你自己在函数里决定。

Playwright 和 Puppeteer:按上下文隔离

浏览器自动化工具本身不做任何轮换,但它们允许每个浏览器上下文使用自己的代理,这正是在同一个浏览器中运行多个独立会话的方式。

  • Playwright 接受一个 proxy 选项,包含 server、username 和 password,既可以在启动时应用于整个浏览器,也可以在 newContext() 时应用于单个上下文。完整设置请参阅我们的 Playwright 集成指南。
  • Puppeteer 通过 --proxy-server 启动参数设置代理,或通过 createBrowserContext({ proxyServer }) 按上下文设置。两者都不支持直接传入凭证:你需要用 page.authenticate() 来回应代理的登录验证。

为每个上下文分配各自的会话,就能做到每个上下文对应一个 IP 和一个 Cookie 存储区,这正是登录态流程所需要的。

Selenium:全浏览器范围,处理密码时较为笨拙

Selenium 通过浏览器选项设置代理,因此会应用于整个浏览器。在 Chrome 中,常见做法是使用 --proxy-server 开关,但它没有位置填写用户名和密码。常见的变通办法是:写一个小型浏览器扩展来应答登录验证,或者搭建一个不带密码的本地转发代理,由它带着凭证把流量转发给你的服务商。曾经很受欢迎的解决方案 Selenium Wire,已于 2024 年 1 月被归档,不再维护。

轮换网关带来的变化

框架层面的轮换是为代理列表设计的:一百对 IP:port,你在其中循环使用、测试、淘汰。轮换住宅网关的工作方式不同。你只需连接到一个主机和端口,由网关来选择出口 IP。这把大部分工作从你的代码中移走了:

  • 轮换发生在网关一侧,所以一个代理 URL 就足够了。只有一个条目的轮询列表不过是个设置项而已。
  • 会话通过用户名来请求。在 Shifter 中,你在用户名里加上 sid-<id> 来保持同一个出口 IP,再加上 ttl-<seconds> 来指定保持的时长,详见粘性代理与轮换代理对比。
  • 地理位置同样作为用户名的一部分,因此爬虫可以在每个请求中指定国家或城市,而无需维护第二份代理列表。

于是,框架的任务就缩减为一件事:把它自己对会话的理解,映射到代理用户名中的会话 ID 上。

接入方式

Crawlee。 传入一个函数,根据 Crawlee 的会话 ID 构建用户名。会话 ID 可能包含下划线等字符,因此只保留字母和数字:

import { CheerioCrawler, ProxyConfiguration } from 'crawlee';

const proxyConfiguration = new ProxyConfiguration({
  newUrlFunction: (sessionId) => {
    const sid = sessionId
      ? `-sid-${String(sessionId).replace(/[^a-zA-Z0-9]/g, '')}-ttl-600`
      : '';
    return `http://customer-USERNAME${sid}:PASSWORD@p.shifter.io:443`;
  },
});

const crawler = new CheerioCrawler({
  proxyConfiguration,
  useSessionPool: true,
  persistCookiesPerSession: true,
  async requestHandler({ request, $ }) {
    console.log(request.url, $('title').text());
  },
});

await crawler.run(['https://example.com/']);

当 Crawlee 淘汰一个被封锁的会话时,下一个会话 ID 会自动生成一个新的粘性 IP。

Scrapy。 一个小型下载器中间件,会在 Scrapy 自身的代理中间件运行之前设置好代理。在 meta 中带有 session 值的请求共享同一个 IP;其余请求则会轮换:

# middlewares.py
class GatewayProxyMiddleware:
    def process_request(self, request, spider):
        sid = request.meta.get("session")
        user = "customer-USERNAME"
        if sid:
            user += f"-sid-{sid}-ttl-600"
        request.meta["proxy"] = f"http://{user}:PASSWORD@p.shifter.io:443"

# settings.py
DOWNLOADER_MIDDLEWARES = {
    "myproject.middlewares.GatewayProxyMiddleware": 350,
}

Playwright。 每个会话对应一个上下文:

const context = await browser.newContext({
  proxy: {
    server: 'http://p.shifter.io:443',
    username: 'customer-USERNAME-sid-cart1-ttl-600',
    password: 'PASSWORD',
  },
});

如何选择

选择框架应该依据站点和团队的需求,而不是它的代理功能。如果你想在 Node.js 中让封锁处理、会话和代理分层都自动完成,Crawlee 是最佳选择。Scrapy 仍然是用 Python 爬取大量纯 HTML 页面最快的方式,它在代理方面的缺口只需十行中间件代码就能补上。当页面需要真实浏览器时,Playwright 或 Puppeteer 才是正确的工具,上下文能为你提供干净的会话。Selenium 也能用,只是在处理凭证时要多花些力气。

在轮换网关之后,这六种工具都可以归结为同一种模式:一个代理 URL,再加上在请求必须共享 IP 的地方,于用户名中放入一个会话 ID。关于如何将其落地到生产环境的爬虫中,可参阅我们的网页抓取用例。

来源与参考资料

常见问题

哪个抓取框架内置的代理管理最完善?

Crawlee。它的 ProxyConfiguration 可以轮换一份代理列表,能用你自己的函数为每个请求挑选代理,在网站开始封锁时可以逐级切换到更高层级的代理,并且将每个会话绑定到同一个代理,使 cookie 和 IP 保持一致。Scrapy、Playwright、Puppeteer 和 Selenium 都接受代理设置,但轮换工作要你自己处理。

Scrapy 会自动轮换代理吗?

不会。Scrapy 的 HttpProxyMiddleware 会把每个请求通过 request.meta['proxy'] 或 http_proxy 和 https_proxy 环境变量中指定的代理发送出去。要在多个代理之间轮换,需要你自己编写中间件,或者使用像 scrapy-rotating-proxies 这样的第三方扩展。

如果我的供应商提供了一个轮换网关,我还需要框架的代理轮换功能吗?

通常不需要。轮换住宅网关会在同一个主机和端口背后帮你更换出口 IP。你仍然需要框架做的是会话处理:对于必须共用同一个 IP 的每个请求,比如登录或结账流程,在代理用户名中发送相同的会话 ID。

为什么我不能在 Chrome 的代理参数里填用户名和密码?

Chrome 的 --proxy-server 开关只接受主机和端口。Puppeteer 通过 page.authenticate 来响应代理的登录验证,Playwright 则在其 proxy 选项中支持填写用户名和密码。Selenium 对 Chrome 没有内置的对应方案,因此人们会使用一个小型浏览器扩展或本地转发代理来解决这个问题。

准备好开始了吗?

试用 Shifter 住宅代理,205M+ 个 IP,195+ 个国家,低至 $0.10/GB。

立即开始