Selenium 代理配置指的是设置浏览器选项或 capabilities,将网页流量经由指定的代理服务器转发,从而实现解除地域封锁、保持匿名以及检查网络流量等任务。对于需要绕过地域限制、从不同网络位置测试网站行为,或在测试与数据抓取过程中管理网络流量的自动化任务来说,这项配置必不可少。
在 Selenium 中使用代理,可以把浏览器的全部流量重定向到中间服务器。该能力在以下场景中至关重要:
* 绕过地域性内容限制。
* 在自动化网页交互过程中保持匿名。
* 测试从不同网络节点访问时网站的性能或行为。
* 监控或调试网络请求与响应。
* 访问内部网络或受限网络。
代理的通用概念
在配置 Selenium 之前,理解代理的基本概念非常关键。
代理类型
- HTTP/HTTPS 代理:这类代理工作在应用层(Layer 7)。HTTP 代理处理未加密的 HTTP 流量,HTTPS 代理处理加密的 HTTPS 流量。许多 HTTPS 代理会进行 SSL 拦截(中间人方式):先解密流量、进行检查,再重新加密后转发。如果浏览器不信任该代理的证书,有时会导致 SSL 证书错误。
- SOCKS 代理(SOCKS4、SOCKS5):SOCKS(Socket Secure)代理工作在更低的层级(Layer 5)。它们与协议无关,也就是说可以处理任意 TCP/UDP 流量,而不仅仅是 HTTP/HTTPS。SOCKS5 是更常见的版本,支持身份验证和 UDP 流量,因此在网页浏览之外的各类应用中都很灵活。
代理身份验证
许多代理服务器需要身份验证(用户名和密码)才能授予访问权限。Selenium 通过把凭据直接嵌入代理字符串来处理基本身份验证,通常格式为 username:password@host:port。
浏览器选项 / capabilities
Selenium 通过特定的驱动可执行文件与浏览器交互(例如 Chrome 使用 ChromeDriver,Firefox 使用 GeckoDriver)。这些驱动接受一个 Options 对象(例如 ChromeOptions、FirefoxOptions),代理设置就在其中定义。这些设置会在浏览器启动时传入,确保该浏览器实例之后的所有流量都经由指定代理转发。
Selenium 代理配置:各语言示例
以下各节详细说明如何使用 Python、Java 和 C# 为 Chrome 和 Firefox 配置代理。相同原理也适用于 Selenium 支持的其他浏览器(如 Edge 或 Safari),只需使用各自的 Options 对象。
Python
Python 使用 selenium.webdriver.Proxy 和 ProxyType,在浏览器选项中定义代理配置。
基础 HTTP/HTTPS 代理
from selenium import webdriver
from selenium.webdriver.common.proxy import Proxy, ProxyType
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions
# 代理设置
PROXY_HOST = "your_proxy_host"
PROXY_PORT = 8080 # 或 HTTPS 使用 443
# --- Chrome 示例 ---
chrome_options = ChromeOptions()
chrome_options.add_argument(f'--proxy-server={PROXY_HOST}:{PROXY_PORT}')
# 可选:若代理导致问题,可关闭 SSL 证书校验(请谨慎使用)
# chrome_options.add_argument('--ignore-certificate-errors')
driver_chrome = webdriver.Chrome(options=chrome_options)
driver_chrome.get("http://www.example.com")
# ... 执行操作 ...
driver_chrome.quit()
# --- Firefox 示例 ---
firefox_options = FirefoxOptions()
firefox_options.set_preference("network.proxy.type", 1) # 手动代理配置
firefox_options.set_preference("network.proxy.http", PROXY_HOST)
firefox_options.set_preference("network.proxy.http_port", PROXY_PORT)
firefox_options.set_preference("network.proxy.ssl", PROXY_HOST)
firefox_options.set_preference("network.proxy.ssl_port", PROXY_PORT)
firefox_options.set_preference("network.proxy.no_proxies_on", "") # 确保所有主机都走代理
driver_firefox = webdriver.Firefox(options=firefox_options)
driver_firefox.get("http://www.example.com")
# ... 执行操作 ...
driver_firefox.quit()
带身份验证的 HTTP/HTTPS 代理
对于需要身份验证的 HTTP/HTTPS 代理,请把凭据直接嵌入代理字符串。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions
PROXY_HOST = "your_proxy_host"
PROXY_PORT = 8080
PROXY_USER = "your_username"
PROXY_PASS = "your_password"
# --- Chrome 示例 ---
# 格式:user:pass@host:port
authenticated_proxy = f"{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}"
chrome_options = ChromeOptions()
chrome_options.add_argument(f'--proxy-server={authenticated_proxy}')
driver_chrome = webdriver.Chrome(options=chrome_options)
driver_chrome.get("http://www.example.com")
driver_chrome.quit()
# --- Firefox 示例 ---
# Firefox 的原生首选项并不直接支持在 HTTP/HTTPS 代理字符串中写入用户名/密码。
# 常见的变通做法是使用浏览器扩展或代理管理器。
# 不过,如果通过 capabilities 使用 "direct" 代理选项(相比 Chrome 的 --proxy-server 参数,
# 这在 Firefox 中较少见),也可能奏效。
# 若要在 Firefox 上稳定使用带认证的代理,建议使用代理扩展或 SOCKS5 代理。
# 下面是一种通用做法,未必对 Firefox 中所有带认证的 HTTP/HTTPS 代理都直接有效。
# 为了简单和跨浏览器一致性,如果必须使用身份验证,建议改用 SOCKS5。
# 标准的 Firefox 首选项不直接支持为 HTTP/HTTPS 嵌入 user:pass。
# 在 Firefox 中使用带认证的 HTTP/HTTPS 代理时,浏览器通常会弹窗索要凭据。
# WebDriver 无法直接与浏览器的这些原生认证弹窗交互。
# 常见的解决方案是使用支持通过 URL 认证的代理(例如某些 SOCKS5 代理),
# 或使用能够处理代理认证的浏览器扩展。
# 本示例中,由于复杂度较高且 WebDriver 无法直接支持浏览器原生认证弹窗,
# 我们省略了 Firefox 中直接配置带认证 HTTP/HTTPS 代理的做法。
SOCKS 代理
SOCKS 代理需要指定 SOCKS 版本。由于功能更完善,通常首选 SOCKS5。
from selenium import webdriver
from selenium.webdriver.common.proxy import Proxy, ProxyType
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions
PROXY_HOST = "your_socks_proxy_host"
PROXY_PORT = 1080 # 常用的 SOCKS 端口
PROXY_USER = "your_username" # SOCKS5 可选
PROXY_PASS = "your_password" # SOCKS5 可选
# --- Chrome 示例 ---
chrome_options = ChromeOptions()
# 带认证的 SOCKS5 格式为 socks5://user:pass@host:port
# 不带认证的 SOCKS5 格式为 socks5://host:port
# SOCKS4 请使用 socks4://host:port
socks_proxy_string = f"socks5://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}" if PROXY_USER else f"socks5://{PROXY_HOST}:{PROXY_PORT}"
chrome_options.add_argument(f'--proxy-server={socks_proxy_string}')
driver_chrome = webdriver.Chrome(options=chrome_options)
driver_chrome.get("http://www.example.com")
driver_chrome.quit()
# --- Firefox 示例 ---
firefox_options = FirefoxOptions()
firefox_options.set_preference("network.proxy.type", 1) # 手动代理配置
firefox_options.set_preference("network.proxy.socks", PROXY_HOST)
firefox_options.set_preference("network.proxy.socks_port", PROXY_PORT)
firefox_options.set_preference("network.proxy.socks_version", 5) # 用于 SOCKS5
firefox_options.set_preference("network.proxy.socks_username", PROXY_USER) # 用于带认证的 SOCKS5
firefox_options.set_preference("network.proxy.socks_password", PROXY_PASS) # 用于带认证的 SOCKS5
firefox_options.set_preference("network.proxy.no_proxies_on", "")
driver_firefox = webdriver.Firefox(options=firefox_options)
driver_firefox.get("http://www.example.com")
driver_firefox.quit()
Java
Java 使用 org.openqa.selenium.Proxy 类,并在浏览器驱动的 capabilities 中设置它。
基础 HTTP/HTTPS 代理
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
public class SeleniumProxySetup {
public static void main(String[] args) {
String PROXY_HOST = "your_proxy_host";
int PROXY_PORT = 8080;
// --- Chrome 示例 ---
ChromeOptions chromeOptions = new ChromeOptions();
Proxy proxyChrome = new Proxy();
proxyChrome.setHttpProxy(PROXY_HOST + ":" + PROXY_PORT);
proxyChrome.setSslProxy(PROXY_HOST + ":" + PROXY_PORT); // HTTPS 也需要设置
chromeOptions.setCapability("proxy", proxyChrome);
WebDriver driverChrome = new ChromeDriver(chromeOptions);
driverChrome.get("http://www.example.com");
// ... 执行操作 ...
driverChrome.quit();
// --- Firefox 示例 ---
FirefoxOptions firefoxOptions = new FirefoxOptions();
Proxy proxyFirefox = new Proxy();
proxyFirefox.setHttpProxy(PROXY_HOST + ":" + PROXY_PORT);
proxyFirefox.setSslProxy(PROXY_HOST + ":" + PROXY_PORT); // HTTPS 也需要设置
firefoxOptions.setCapability("proxy", proxyFirefox);
WebDriver driverFirefox = new FirefoxDriver(firefoxOptions);
driverFirefox.get("http://www.example.com");
// ... 执行操作 ...
driverFirefox.quit();
}
}
带身份验证的 HTTP/HTTPS 代理
与 Python 类似,基础的 HTTP/HTTPS 身份验证同样把凭据嵌入代理字符串。
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
// 由于原生弹窗的存在,Firefox 带认证 HTTP/HTTPS 代理的示例较为复杂。
// Firefox 的认证场景建议考虑 SOCKS5 或浏览器扩展。
public class SeleniumAuthenticatedProxySetup {
public static void main(String[] args) {
String PROXY_HOST = "your_proxy_host";
int PROXY_PORT = 8080;
String PROXY_USER = "your_username";
String PROXY_PASS = "your_password";
// --- Chrome 示例 ---
ChromeOptions chromeOptions = new ChromeOptions();
Proxy proxyChrome = new Proxy();
// 格式:user:pass@host:port
String authenticatedProxyString = PROXY_USER + ":" + PROXY_PASS + "@" + PROXY_HOST + ":" + PROXY_PORT;
proxyChrome.setHttpProxy(authenticatedProxyString);
proxyChrome.setSslProxy(authenticatedProxyString); // HTTPS 也需要设置
chromeOptions.setCapability("proxy", proxyChrome);
WebDriver driverChrome = new ChromeDriver(chromeOptions);
driverChrome.get("http://www.example.com");
driverChrome.quit();
// --- Firefox 示例 ---
// 如 Python 部分所述,在没有浏览器扩展的情况下,Firefox 的原生首选项
// 不支持通过 WebDriver capabilities 直接为 HTTP/HTTPS 代理嵌入用户名/密码。
// 浏览器通常会弹窗索要凭据。
// 若要在 Firefox 上稳定使用带认证的代理,建议使用 SOCKS5 代理或代理扩展。
}
}
SOCKS 代理
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
public class SeleniumSocksProxySetup {
public static void main(String[] args) {
String PROXY_HOST = "your_socks_proxy_host";
int PROXY_PORT = 1080; // 常用的 SOCKS 端口
String PROXY_USER = "your_username"; // SOCKS5 可选
String PROXY_PASS = "your_password"; // SOCKS5 可选
// --- Chrome 示例 ---
ChromeOptions chromeOptions = new ChromeOptions();
Proxy proxyChrome = new Proxy();
// 带认证的 SOCKS5 格式为 socks5://user:pass@host:port
// 不带认证的 SOCKS5 格式为 socks5://host:port
String socksProxyString = PROXY_USER != null && !PROXY_USER.isEmpty()
? "socks5://" + PROXY_USER + ":" + PROXY_PASS + "@" + PROXY_HOST + ":" + PROXY_PORT
: "socks5://" + PROXY_HOST + ":" + PROXY_PORT;
chromeOptions.addArguments("--proxy-server=" + socksProxyString); // Chrome 通过 --proxy-server 参数使用 SOCKS
WebDriver driverChrome = new ChromeDriver(chromeOptions);
driverChrome.get("http://www.example.com");
driverChrome.quit();
// --- Firefox 示例 ---
FirefoxOptions firefoxOptions = new FirefoxOptions();
Proxy proxyFirefox = new Proxy();
proxyFirefox.setSocksProxy(PROXY_HOST + ":" + PROXY_PORT);
proxyFirefox.setSocksVersion(5); // 用于 SOCKS5
// Firefox 中用于 SOCKS 认证的首选项
firefoxOptions.setPreference("network.proxy.socks_username", PROXY_USER);
firefoxOptions.setPreference("network.proxy.socks_password", PROXY_PASS);
firefoxOptions.setCapability("proxy", proxyFirefox);
WebDriver driverFirefox = new FirefoxDriver(firefoxOptions);
driverFirefox.get("http://www.example.com");
driverFirefox.quit();
}
}
C
C# 使用 OpenQA.Selenium.Proxy 类,并在浏览器选项中设置它。
基础 HTTP/HTTPS 代理
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
public class SeleniumProxySetup
{
public static void Main(string[] args)
{
string PROXY_HOST = "your_proxy_host";
int PROXY_PORT = 8080;
// --- Chrome 示例 ---
ChromeOptions chromeOptions = new ChromeOptions();
Proxy proxyChrome = new Proxy();
proxyChrome.HttpProxy = $"{PROXY_HOST}:{PROXY_PORT}";
proxyChrome.SslProxy = $"{PROXY_HOST}:{PROXY_PORT}"; // HTTPS 也需要设置
chromeOptions.Proxy = proxyChrome;
IWebDriver driverChrome = new ChromeDriver(chromeOptions);
driverChrome.Navigate().GoToUrl("http://www.example.com");
// ... 执行操作 ...
driverChrome.Quit();
// --- Firefox 示例 ---
FirefoxOptions firefoxOptions = new FirefoxOptions();
Proxy proxyFirefox = new Proxy();
proxyFirefox.HttpProxy = $"{PROXY_HOST}:{PROXY_PORT}";
proxyFirefox.SslProxy = $"{PROXY_HOST}:{PROXY_PORT}"; // HTTPS 也需要设置
firefoxOptions.Proxy = proxyFirefox;
IWebDriver driverFirefox = new FirefoxDriver(firefoxOptions);
driverFirefox.Navigate().GoToUrl("http://www.example.com");
// ... 执行操作 ...
driverFirefox.Quit();
}
}
带身份验证的 HTTP/HTTPS 代理
基础身份验证请把凭据嵌入代理字符串。
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
// 由于原生弹窗的存在,Firefox 带认证 HTTP/HTTPS 代理的示例较为复杂。
// Firefox 的认证场景建议考虑 SOCKS5 或浏览器扩展。
public class SeleniumAuthenticatedProxySetup
{
public static void Main(string[] args)
{
string PROXY_HOST = "your_proxy_host";
int PROXY_PORT = 8080;
string PROXY_USER = "your_username";
string PROXY_PASS = "your_password";
// --- Chrome 示例 ---
ChromeOptions chromeOptions = new ChromeOptions();
Proxy proxyChrome = new Proxy();
// 格式:user:pass@host:port
string authenticatedProxyString = $"{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}";
proxyChrome.HttpProxy = authenticatedProxyString;
proxyChrome.SslProxy = authenticatedProxyString; // HTTPS 也需要设置
chromeOptions.Proxy = proxyChrome;
IWebDriver driverChrome = new ChromeDriver(chromeOptions);
driverChrome.Navigate().GoToUrl("http://www.example.com");
driverChrome.Quit();
// --- Firefox 示例 ---
// 如 Python 和 Java 部分所述,在没有浏览器扩展的情况下,Firefox 的原生首选项
// 不支持通过 WebDriver capabilities 直接为 HTTP/HTTPS 代理嵌入用户名/密码。
// 浏览器通常会弹窗索要凭据。
// 若要在 Firefox 上稳定使用带认证的代理,建议使用 SOCKS5 代理或代理扩展。
}
}
SOCKS 代理
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
public class SeleniumSocksProxySetup
{
public static void Main(string[] args)
{
string PROXY_HOST = "your_socks_proxy_host";
int PROXY_PORT = 1080; // 常用的 SOCKS 端口
string PROXY_USER = "your_username"; // SOCKS5 可选
string PROXY_PASS = "your_password"; // SOCKS5 可选
// --- Chrome 示例 ---
ChromeOptions chromeOptions = new ChromeOptions();
// Chrome 通过 --proxy-server 参数使用 SOCKS。
// 带认证的 SOCKS5 格式为 socks5://user:pass@host:port
// 不带认证的 SOCKS5 格式为 socks5://host:port
string socksProxyString = string.IsNullOrEmpty(PROXY_USER)
? $"socks5://{PROXY_HOST}:{PROXY_PORT}"
: $"socks5://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}";
chromeOptions.AddArgument($"--proxy-server={socksProxyString}");
IWebDriver driverChrome = new ChromeDriver(chromeOptions);
driverChrome.Navigate().GoToUrl("http://www.example.com");
driverChrome.Quit();
// --- Firefox 示例 ---
FirefoxOptions firefoxOptions = new FirefoxOptions();
Proxy proxyFirefox = new Proxy();
proxyFirefox.SocksProxy = $"{PROXY_HOST}:{PROXY_PORT}";
proxyFirefox.SocksVersion = 5; // 用于 SOCKS5
// Firefox 中用于 SOCKS 认证的首选项
firefoxOptions.SetPreference("network.proxy.socks_username", PROXY_USER);
firefoxOptions.SetPreference("network.proxy.socks_password", PROXY_PASS);
firefoxOptions.Proxy = proxyFirefox;
IWebDriver driverFirefox = new FirefoxDriver(firefoxOptions);
driverFirefox.Navigate().GoToUrl("http://www.example.com");
driverFirefox.Quit();
}
}
代理类型对比
| 特性 | HTTP 代理 | HTTPS 代理 | SOCKS 代理(SOCKS5) |
|---|---|---|---|
| 协议层级 | 应用层(Layer 7) | 应用层(Layer 7) | 会话层(Layer 5) |
| 处理的流量 | 仅 HTTP 流量 | 仅加密的 HTTP(HTTPS)流量 | 任意 TCP/UDP 流量 |
| 加密 | 无(客户端到代理) | 客户端到代理(可重新加密) | 无(客户端到代理),应用层加密仍然有效 |
| 匿名性 | 可能在请求头中暴露原始 IP | 更好,但仍然是代理 | 高,更加与协议无关,请求头改动更少 |
| 身份验证 | Basic、Digest(通过请求头) | Basic、Digest(通过请求头) | 用户名/密码、GSS-API |
| 使用场景 | 普通网页浏览、缓存、内容过滤 | 安全网页浏览、敏感数据、SSL 检查 | 通用用途、P2P、游戏、类似 VPN 的功能 |
| 性能 | 处理 HTTP 通常更快 | 加解密带来额外开销 | 因在更低层处理,可能更慢 |
常见问题与排查
- 代理不工作:核对代理主机和端口。确认代理服务器在线,且运行 Selenium 的机器可以访问它。防火墙规则可能拦截了到代理的连接。
- 身份验证失败:仔细核对用户名和密码。确认代理支持 Selenium 使用的认证方式(通常是通过 URL 嵌入的基本认证)。
- SSL 证书错误:如果 HTTPS 代理执行 SSL 拦截,浏览器可能报出证书警告,因为它不信任代理动态生成的证书。可选做法包括:
- 关闭证书校验(例如 Chrome 的
--ignore-certificate-errors),但这存在安全风险,不建议用于生产环境。 - 将代理的根证书安装到浏览器的信任存储中。
- 关闭证书校验(例如 Chrome 的
- 超时错误:代理服务器可能速度慢、负载过高或存在网络问题。增加 Selenium 的隐式或显式等待时间,或换一个代理测试。
- 各浏览器的差异:虽然总体方法一致,但各浏览器驱动在处理代理设置上存在细微差别。若遇到异常行为,请查阅对应浏览器的文档。
最佳实践
- 用环境变量保存凭据:不要把敏感的代理用户名和密码硬编码在脚本中。应从环境变量或安全的配置管理系统中读取。
- 专用代理管理器:对于轮换代理、管理大量代理列表或实现高级代理逻辑等复杂场景,建议使用专门的代理管理库或商业代理服务的 SDK。
- 错误处理:实现健壮的
try-catch代码块,妥善处理代理连接失败、认证错误或网络超时。 - 无头模式兼容性:代理配置可与浏览器的无头模式无缝配合,这对服务器端自动化很有帮助。
