Selenium 使用代理 IP 访问目标站的排障清单
Selenium 使用代理 IP 访问目标站失败时,按浏览器启动、代理参数、认证、出口检测、DNS/WebRTC、状态码和浏览器日志逐层排查。
Selenium 接入代理 IP 后,按“浏览器能否启动→代理参数是否生效→认证是否成功→HTTP 出口是否变化→DNS/WebRTC 是否异常→目标站返回什么”排查。先用出口检测页完成一次最小验证,再访问目标站;否则驱动、认证、网络出口和目标站规则会混在一起。本清单面向已获授权或公开可访问页面的访问排障;遇到 429 应遵守目标站限流,主动降低并发并延长请求间隔。
先确认 Selenium 能正常启动浏览器
先暂时不访问业务网站,只启动空白浏览器。Selenium 4.6 及以上版本通常可由 Selenium Manager 管理驱动,但浏览器版本、Selenium 版本和企业网络仍可能影响驱动获取与启动。
```python
from selenium import webdriver
driver = webdriver.Chrome()
print(driver.capabilities.get("browserVersion"))
driver.quit()
```
如果这一步失败,先处理浏览器路径、驱动下载、版本或权限问题,不要把浏览器无法启动归因于代理 IP。
Selenium 的浏览器选项可对照官方文档。
代理协议、主机、端口和认证字段可同时对照代理设置帮助核验。
再用无认证代理完成最小出口验证
下面示例把 HTTP 代理参数传给 Chromium。HOST 和 PORT 使用后台显示的实际值。
```python
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--proxy-server=http://HOST:PORT")
options.set_capability("goog:loggingPrefs", {"browser": "ALL"})
driver = webdriver.Chrome(options=options)
driver.set_page_load_timeout(30)
driver.get("https://api.ipify.org?format=json")
print(driver.find_element("tag name", "body").text)
driver.save_screenshot("proxy-check.png")
driver.quit()
```
预期结果是页面返回代理出口 IP。若仍为本地公网 IP,检查代理参数是否在创建 webdriver.Chrome() 前加入、是否复用了旧 driver、协议和端口是否对应,以及系统代理或其他启动参数是否发生冲突。
按协议分别配置 HTTP、HTTPS 和 SOCKS5
也可以通过 Selenium 的代理能力显式设置。HTTP/HTTPS 和 SOCKS5 应分开配置,不要把协议当成同一入口。
```python
from selenium import webdriver
from selenium.webdriver.common.proxy import Proxy, ProxyType
proxy = Proxy()
proxy.proxy_type = ProxyType.MANUAL
proxy.http_proxy = "HOST:PORT"
proxy.ssl_proxy = "HOST:PORT"
options = webdriver.ChromeOptions()
options.proxy = proxy
driver = webdriver.Chrome(options=options)
driver.get("https://api.ipify.org?format=json")
print(driver.find_element("tag name", "body").text)
driver.quit()
```
SOCKS5 场景应设置 socks_proxy 和 socks_version = 5,并使用对应端口。某个端口支持 HTTP 不代表它也支持 SOCKS5。
带账号密码的认证要单独验证
Chromium 的 --proxy-server 只指定代理主机和端口,不能保证所有版本和模式都能直接携带账号密码。若代理 IP 需要账号密码认证,应按当前浏览器和 Selenium 版本选择受支持的认证方式,并先在有头模式验证。认证扩展、DevTools/BiDi 方案或客户端能力可能随版本变化,不要假设某个扩展在所有无头模式都可用。
出现 407 时按以下顺序检查:
1. 账号、密码是否来自同一组代理信息。
2. 协议和端口是否与后台显示一致。
3. 认证逻辑是否在首次页面请求前生效。
4. 有头模式是否成功、无头模式是否失败。
5. 使用同一组参数在浏览器外的测试客户端中是否能通过认证。
407 表示代理认证失败,不是目标站拒绝访问。
出口正确后,再分别验证 DNS 和 WebRTC
| 检测结果 | 说明 | 下一步 |
|---|---|---|
| HTTP 出口仍是本地公网 IP | 代理参数未生效或当前流量未被接管 | 查启动参数、driver 实例和协议端口 |
| HTTP 出口正确,DNS 异常 | DNS 解析路径与页面出口不同 | 查浏览器、系统 DNS 和 SOCKS 解析方式 |
| HTTP 出口正确,WebRTC 显示局域网地址 | 实时通信能力存在额外暴露面 | 单独限制不需要的 WebRTC 能力 |
| 三项正常,目标站 403/429/验证码 | 代理接入已生效 | 查账号、Cookie、频率和目标站规则 |
WebRTC 显示本地候选地址不自动等于普通 HTTP 请求直连,必须先看 HTTP 出口检测结果。
最后保存浏览器日志和失败现场
```python
from pathlib import Path
Path("page.html").write_text(driver.page_source, encoding="utf-8")
driver.save_screenshot("failed-page.png")
for entry in driver.get_log("browser"):
print(entry["level"], entry["message"])
```
同时记录目标 URL、时间、浏览器版本、Selenium 版本、代理协议、脱敏后的代理标识、出口 IP、状态码或页面提示。不要在日志中保存完整密码。
根据启动、认证、出口和目标站报错选择排障分支
| 现象 | 优先原因 | 处理动作 |
|---|---|---|
| 浏览器无法启动 | 浏览器/驱动/权限 | 先不带代理启动,确认基础环境 |
ERR_PROXY_CONNECTION_FAILED | 主机、端口、网络或资源状态 | 核对后台参数,用另一客户端复测 |
| 407 | 认证失败 | 重核账号密码和认证方式 |
| 出口仍是本地 IP | 启动参数或接管范围 | 重建 driver,移除冲突参数 |
| 出口正确但目标站 403 | 权限、目标站规则或账号状态 | 固定出口做单变量对照 |
| 出口正确但目标站 429 | 请求频率或配额 | 读取限流信息,先降并发和延长间隔 |
| 有头成功、无头失败 | 模式或版本差异 | 保持其他参数不变,记录网络与页面差异 |
用最小对照实验确认问题来自浏览器还是代理 IP
保持目标 URL、账号、Cookie、浏览器版本和代理 IP 不变,依次只改变一个条件:有头/无头、扩展开/关、系统代理开/关。每组先测出口再测目标站。只有在少数代理 IP 上稳定失败、其他条件相同且换出口后恢复,才进一步检查出口质量或地区识别。
每组实验至少保存一张失败截图和一份浏览器日志,并标注对应的出口 IP 与时间。截图只能说明页面当时呈现的结果,不能替代状态码、认证信息和网络日志。
用脱敏复测数据验证 Selenium 排障结果
以下为脱敏记录示例(目标站、驱动版本和 IP 已隐去,数字不是 SLA):Chrome 129 + Selenium 4.25,HTTP 代理启动 20 次;浏览器启动 20/20,出口检测为代理地区 19/20,目标页 403 为 3/20。改用同版本有头模式并固定 Cookie 后,403 为 1/20。该观察不能证明有头模式普遍更优。
启动能力与代理边界可核对 Selenium 官方文档,协议错误语义可核对 W3C WebDriver;版本、样本量和阈值属于实操经验。
FAQ
WebDriver 版本不一致会影响代理参数吗?
可能影响浏览器启动和能力加载。先证明不带代理能启动,再加入代理参数,才能定位是哪一层失败。
出口 IP 正确就代表配置完全正常吗?
不代表。还要检查 DNS、WebRTC、子请求和目标页面响应,但出口正确至少说明普通页面请求已经经过代理 IP。
认证扩展适合所有浏览器模式吗?
不适合一概而论。不同 Chromium 和 Selenium 版本对扩展、无头模式和认证能力的支持可能不同,应先在当前版本实测。
什么时候选择动态或静态住宅代理 IP?
多地区公开页面采样可评估动态住宅代理 IP;连续登录或长会话任务更适合静态住宅代理 IP。选型应在接入链路验证通过后进行。
完成排障后,可按会话需求查看静态住宅代理 IP。
