Geonode logo
Carl Gamutan

Carl Gamutan

更新于:2026年10月7日

发布于:2026年10月2日

如何在 Scrapy 中使用代理

Scrapy 是一个用于大规模爬取和提取数据的 Python 框架。以下将介绍如何将其与代理服务器连接、设置代理轮换或粘性会话,以及如何解决由此引发的错误。

为什么 Scrapy 需要代理

Scrapy 的代理功能允许该工具通过不同的 IP 地址建立连接,而不是始终使用运行它的机器的 IP 地址。这对于基于位置的任务、测试、监控以及其他需要考虑连接来源的任务非常有用。

Scrapy 仍负责处理主要任务,而代理则负责管理连接的来源。

没有代理会怎样:IP封禁、速率限制、地理限制

如果没有代理,网站会持续检测到同一个IP地址。随着访问量增加,该IP可能会触发速率限制或被封禁。

地理位置同样重要。从德国访问的页面可能与从美国访问的页面显示的内容不同。

Scrapy 代理使您能够在需要时通过不同的 IP 地址和地理位置进行连接。

Scrapy 应使用哪种代理类型

合适的代理类型取决于具体任务。

代理类型爬取账户管理测试监控
住宅型当位置和 IP 来源重要时适用当账户需要住宅 IP 时有用适用于基于位置的测试适用于检查不同位置的内容
ISP需要稳定 IP 时效果良好适用于在单一 IP 上进行较长时间的会话适合使用固定 IP 进行测试适用于从同一 IP 进行持续检查
数据中心适合追求速度和较大请求量当不需要住宅 IP 时更佳适合常规测试适合频繁的自动化检查

当 IP 来源和位置至关重要时,住宅代理非常有用。当需要同一 IP 保持更长时间的活跃状态时,ISP 代理表现出色。当主要关注速度和规模时,数据中心代理是理想选择。

最佳选择还取决于任务是否需要地理定位、稳定的连接,或是访问更大的IP池。

如何在 Scrapy 中连接代理

Scrapy 的代理配置需要 Geonode 的主机、端口、用户名和密码。请将这些凭据保存在环境变量中,然后在代码中配置代理时加载它们。

使用 Geonode 服务?请从 访问凭据 中获取用户名和密码,并从 代理服务器信息 中获取主机、端口和协议。

配置路径或代码

在我们的测试中,我们添加了一个下载器中间件:

DOWNLOADER_MIDDLEWARES = {
    "geonode_scrapy.middlewares.GeonodeProxyMiddleware": 350,
    "scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": 400,
}

该中间件通过 ``request.meta["proxy"]`

传递代理 URL,Scrapy 的 ``HttpProxyMiddleware

` 随后会使用该 URL:

request.meta["proxy"] = proxy_url

您也可以将代理直接传递给单个请求:

yield scrapy.Request(
    url,
    meta={"proxy": proxy_url},
)

请将实际的用户名和密码保存在环境变量中,而不是直接写在 Python 文件里。在我们的测试中,此配置成功通过代理返回了 HTTP 200 状态码。

身份验证格式为 host:port:user:pass,

Geonode

提供了四个参数:

proxy.geonode.io:PORT:USERNAME:PASSWORD

Scrapy 需要与代理 URL 相同的详细信息:

http://USERNAME:PASSWORD@proxy.geonode.io:PORT

将凭据或完整的代理值存储在环境变量中:

GEONODE_PROXY_URL=http://USERNAME:PASSWORD@proxy.geonode.io:PORT

然后在 Python 中加载它:

import os

proxy_url = os.environ["GEONODE_PROXY_URL"]

对于我们的 HTTP 测试,最终格式为:

http://USERNAME:PASSWORD@proxy.geonode.io:9000

为了验证身份验证,我们还使用错误的凭据发送了请求。 Scrapy 收到了 HTTP 407 状态码,响应内容为:

Authentication error. Please check your authentication settings.

Scrapy 通过 HttpErrorMiddleware

将响应呈现为 HttpError('Ignoring non-200 response')

。

Scrapy 中的 IP 轮换与粘性会话

如果请求无需保持相同的 IP 地址,请使用 IP 轮换。

在我们的测试中,我们将 Geonode

这个轮换代理传递给了 Scrapy:

proxy_url = "http://USERNAME:PASSWORD@proxy.geonode.io:9000"

yield scrapy.Request(
    url,
    meta={"proxy": proxy_url},
)

我们发起了五个连续的请求:

Request 1: 101.98.231.191
Request 2: 101.98.231.191
Request 3: 101.98.231.191
Request 4: 122.164.83.189
Request 5: 122.164.83.189

Unique IPs: 2
Rotation: Yes

测试结果证实了 IP 轮换确实发生了,但并非每次请求的 IP 都会改变。

如果相关请求需要保持在同一 IP 上,请改用粘性会话:

proxy_url = (
    "http://USERNAME-session-blogtest01-lifetime-10:"
    "PASSWORD@proxy.geonode.io:10000"
)

我们使用同一会话发起了三个请求:

Request 1: 177.73.202.78
Request 2: 177.73.202.78
Request 3: 177.73.202.78

Same IP: Yes

在我们的测试中,这三个请求均使用了相同的 IP。

有关可用设置,请参阅 Geonode

指南中的 轮换代理 和 粘性会话。

Scrapy 中常见的代理错误及解决方法

如果代理无法正常工作,请先检查连接信息。先核对用户名和密码,然后检查主机、端口和协议。Scrapy 返回的错误信息通常有助于缩小问题范围。

407 需要代理身份验证

407 错误通常表明存在身份验证问题。

当我们在测试 Scrapy 时使用了错误的凭据,代理返回了以下响应:

HTTP status: 407
Authentication error. Please check your authentication settings.

请先检查用户名和密码。如果凭据正确,请确保 Scrapy 接收到的代理 URL 包含完整的协议、凭据、主机和端口信息。

ERR_TUNNEL_CONNECTION_FAILED / 连接被拒绝

连接错误通常意味着 Scrapy 无法连接到代理服务器。

请先检查主机名和端口。然后确保协议与所使用的代理服务器匹配。

Scrapy 不一定会返回类似浏览器的 ERR_TUNNEL_CONNECTION_FAILED 错误。在我们的连接失败测试中,Scrapy 重试了请求,最终返回了包含 Twisted ConnectionLost 错误的 DownloadFailedError。

超时与空响应

超时是指请求在配置的时间内未收到响应。

首先,检查目标 URL 是否正常,以及代理是否能连接。如果两者均正常,请检查 Scrapy 中的超时配置。

在我们的连接失败测试中,我们使用了 DOWNLOAD_TIMEOUT=5

这个无效的代理端口。重试后,Scrapy 返回:

DownloadFailedError(
  ConnectionLost:
  Connection to the other side was lost in a non-clean fashion.
)

。因此,代理连接失败可能会表现为连接错误,而非简单的超时提示。

一个与Scrapy相关的常见错误

一个容易出现的、与Scrapy相关的错误是将不完整的值传递给request.meta["proxy"]

。

在我们的测试中,我们使用了:

proxy.geonode.io:9000

,但未包含协议或凭据。该请求返回了HTTP 407错误。

解决方法是传入完整的代理 URL:

http://USERNAME:PASSWORD@proxy.geonode.io:9000

,或者让下载器中间件根据环境变量自动生成该 URL。

Scrapy + Geonode:您将获得什么

Scrapy 负责处理应用程序中的请求或连接。Geonode 负责处理代理连接。

您可以根据任务需求选择家庭、ISP 或数据中心代理,并在需要时使用轮询、粘性会话和地理定位功能。这样可以将代理配置与应用程序的其他代码分离。

套餐根据代理类型而异,部分选项按 GB 计费。

常见问题解答

Scrapy 是否支持 SOCKS5 代理?

在我们测试的 Scrapy 版本中,SOCKS5 需要额外配置。

尝试通过 Scrapy 的默认 HTTP 处理程序使用 socks5:// 代理时,出现以下错误:

UnsupportedURLSchemeError("Unsupported scheme: b'socks5'")

随后,我们安装了 httpx2[socks] 并配置了 Scrapy 的实验性 HttpxDownloadHandler。使用端口 11000 上的 SOCKS5 轮转代理后,请求成功返回 HTTP 200 状态码并获取了代理 IP。由于该处理程序尚处于实验阶段,因此更适合用于测试,而非生产环境推荐方案。

在 Scrapy 中能否按请求轮换 IP 地址?

是的,Scrapy 可以通过轮换代理发送请求,但不能保证每个请求都会使用不同的 IP 地址。

我们在五次请求的测试中获得了两个唯一的 IP 地址。前三个请求共用一个 IP 地址,而最后两个请求共用另一个 IP 地址,这证实了测试过程中确实发生了 IP 轮换。

有免费试用吗?

有。Geonode 提供免费试用,因此您可以在升级到付费套餐之前,先用 Scrapy 测试该代理服务。查看当前的免费试用和套餐。

在 Scrapy 中应该在哪里配置代理?

对于单个请求,可通过 request.meta["proxy"] 传递代理。

如果多个请求需要使用相同的代理配置,下载器中间件可将代理逻辑集中管理。在我们的测试中,自定义中间件在 Scrapy 的内置 HttpProxyMiddleware 处理请求之前,先设置了 request.meta["proxy"]。

为什么我的 Scrapy 蜘蛛虽然运行了,却没有发送任何请求?

请检查蜘蛛是如何生成其第一个请求的。

在我们的 Scrapy 2.19 测试中,仅定义了旧版 ``start_requests()`

方法会导致蜘蛛在未发送任何请求的情况下就启动并关闭。使用异步的 ``start()

` 方法解决了此问题:

async def start(self):
    yield scrapy.Request(...)

这是我们在测试环境中记录到的行为。