最近用 Scrapy 写一个数据采集项目,需要从海外站点抓取公开数据。本地测试正常,但部署到腾讯云服务器后,频繁出现两种报错:
407 Authentication RequiredTunnel connection failed: 502 Bad Gateway排查了一圈,问题出在 Scrapy 的网络出口中间件配置上,以及出口 IP 的类型。本文记录完整的排查过程和解决方案。
Scrapy 自带的 HttpProxyMiddleware 支持从 request.meta['proxy'] 读取网络出口地址,但不支持在 URL 里直接嵌入用户名密码。如果写成下面这样,就会一直返回 407:
# 错误写法:认证信息写在 URL 里,Scrapy 不认
yield scrapy.Request(
url,
meta={"proxy": "http://user:pass@gateway.example.com:1080"}
)Scrapy 需要单独的 proxy_auth 参数来传递认证信息。正确写法是在 meta 里同时设置 proxy 和 proxy_auth:
import scrapy
from scrapy.http import Request
class MySpider(scrapy.Spider):
name = "myspider"
def start_requests(self):
proxy = "http://gateway.example.com:1080"
proxy_auth = "user:pass" # 格式为 用户名:密码
yield Request(
url="https://example.com/api/data",
meta={
"proxy": proxy,
"proxy_auth": proxy_auth
},
callback=self.parse
)认证问题解决后,仍然频繁出现 Tunnel connection failed: 502 Bad Gateway,尤其是下载大文件或持续请求时。用 curl 单独测试,速度只有几十 KB/s,且经常中断。
用 ipinfo.io 查看服务器出口 IP 的 ASN 归属,发现是某云服务商的数据中心网段。很多海外站点对数据中心 IP 有速率限制,表现为:能连上,但响应慢,大流量请求容易被网关掐断。
解决方案是切换到住宅 IP 出口。住宅 IP 的 ASN 归属于当地运营商,不会被目标站点判定为机房流量,连接稳定性明显改善。
以下是在 Scrapy 中配置住宅 IP 出口的完整示例:
# ============================================
# 使用住宅 IP 作为 Scrapy 网络出口
# 住宅 IP 服务:1024Proxy
# 官网:https://1024proxy.com/?kwd=hyj-txy
# ============================================
import scrapy
from scrapy.http import Request
from scrapy.crawler import CrawlerProcess
class MySpider(scrapy.Spider):
name = "myspider"
custom_settings = {
"DOWNLOADER_MIDDLEWARES": {
"scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": 100,
},
"DOWNLOAD_TIMEOUT": 30,
"RETRY_ENABLED": True,
"RETRY_TIMES": 3,
}
def start_requests(self):
# 从 1024Proxy 后台获取的住宅 IP 信息
proxy = "http://gateway.1024proxy.com:端口"
proxy_auth = "用户名:密码"
urls = [
"https://example.com/api/data?page=1",
"https://example.com/api/data?page=2",
]
for url in urls:
yield Request(
url=url,
meta={
"proxy": proxy,
"proxy_auth": proxy_auth,
},
callback=self.parse
)
def parse(self, response):
self.logger.info(f"成功获取: {response.url}, 状态码: {response.status}")
if __name__ == "__main__":
process = CrawlerProcess()
process.crawl(MySpider)
process.start()如果使用 scrapy-redis 做分布式爬虫,网络出口配置可以放在 settings.py 中统一管理,并通过中间件动态切换。
Scrapy 默认的并发请求数是 16,如果网络出口服务商的并发限制较低,可能会出现连接排队甚至超时。可以通过以下配置调整:
# settings.py
CONCURRENT_REQUESTS = 10 # 降低并发数
CONCURRENT_REQUESTS_PER_DOMAIN = 5
DOWNLOAD_DELAY = 1.5 # 请求间隔
RANDOMIZE_DOWNLOAD_DELAY = True适当降低并发并加入随机延迟,可以显著减少被目标站点限流的概率。
认证信息不要硬编码:建议将用户名、密码放在环境变量或配置文件中,避免泄露。
定期检查出口 IP 可用性:住宅 IP 虽然稳定,但也可能因长时间大量请求被临时限制。建议在爬虫中集成健康检查,发现异常时自动切换。
先小规模测试:新配置的网络出口上线前,先用少量请求验证连通性和速度,确认无误后再扩大规模。
Scrapy 网络出口配置的两个核心问题:认证参数要单独传,出口 IP 要选住宅类型。前者是配置技巧,后者是网络基础。两者都处理好,数据采集的稳定性会有明显提升。
本文仅做技术交流,请遵守相关平台规则与法律法规。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。