跳转到内容

如何在 Python 中为 Selenium 配置代理:完整指南

Инструменты
如何在 Python 中为 Selenium 配置代理:完整指南

在 Python 中为 Selenium 配置代理,需要通过浏览器专用选项传入代理设置,或者对需要认证的会话使用 Selenium-wire 这类中间件库。对于无需认证的标准 HTTP 或 SOCKS5 代理,ChromeOptions 中的 --proxy-server 参数是最高效的方式;而带认证的代理通常需要自定义浏览器扩展或支持代理的驱动。

为什么 Selenium 自动化必须集成代理

Selenium 是强大的网页自动化工具,但它的默认行为——从单一的静态 IP 地址发出请求——使其极易触发限流和 IP 封禁。在进行大规模数据抓取或跨地区自动化测试时,代理充当中间层,隐藏您的真实来源,并把请求分散到多个 IP 地址上。

使用 GProxy 这样的服务,可以获得住宅代理和数据中心代理池,避免网站把流量识别为来自单一自动化来源。这在以下场景尤为关键:

  • 网页抓取:绕过 Cloudflare、Akamai 等按 IP 监控请求频率的反机器人机制。
  • 本地化测试:验证网站为特定国家的用户显示了正确的货币、语言和内容。
  • 广告核验:确保广告被正确投放给目标受众,没有被拦截或跳转。
  • 压力测试:模拟来自不同地理位置的流量,测试服务器响应时间和 CDN 效率。
如何在 Python 中为 Selenium 配置代理:完整指南

Chrome 和 Firefox 的基础代理配置

在 Selenium 中启用代理最直接的方式是使用浏览器原生选项。该方法最适合“IP 白名单”类代理:代理服务商(例如 GProxy)授权您服务器的 IP 地址,连接串中无需用户名和密码。

使用 Options 配置 Chrome

在 Chrome 中使用 add_argument 方法。这是最快的实现方式,对浏览器启动时间的额外开销可以忽略不计。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

proxy_ip_port = "gw.gproxy.com:10000"

chrome_options = Options()
chrome_options.add_argument(f'--proxy-server={proxy_ip_port}')

driver = webdriver.Chrome(options=chrome_options)
driver.get("https://api.ipify.org?format=json")
print(driver.page_source)
driver.quit()

使用 Proxy 对象配置 Firefox

Firefox 处理代理的方式不同,通常使用 selenium.webdriver.common.proxy 中的 Proxy 对象。这样可以更精细地控制哪些协议(HTTP、SSL、SOCKS)走代理。

from selenium import webdriver
from selenium.webdriver.common.proxy import Proxy, ProxyType

proxy_host = "gw.gproxy.com:10000"

proxy = Proxy()
proxy.proxy_type = ProxyType.MANUAL
proxy.http_proxy = proxy_host
proxy.ssl_proxy = proxy_host

options = webdriver.FirefoxOptions()
options.proxy = proxy

driver = webdriver.Firefox(options=options)
driver.get("https://httpbin.org/ip")
driver.quit()

在 Selenium 中处理代理认证

标准 Selenium 并不原生支持通过 --proxy-server 参数使用需要用户名和密码的代理。如果尝试使用 http://user:pass@host:port,Chrome 通常会忽略凭据,或弹出 Selenium 难以操作的浏览器原生弹窗。要解决这个问题,主要有两种专业做法。

方法一:使用 Selenium-wire

Selenium-wire 是 Selenium 的封装层,扩展了检查请求与响应的能力,更重要的是能透明地处理代理认证。它通过运行一个本地代理服务器来拦截流量并注入所需的认证头。

from seleniumwire import webdriver

# GProxy 凭据与接入点
proxy_options = {
    'proxy': {
        'http': 'http://username:[email protected]:10000',
        'https': 'https://username:[email protected]:10000',
        'no_proxy': 'localhost,127.0.0.1'
    }
}

driver = webdriver.Chrome(seleniumwire_options=proxy_options)
driver.get("https://www.gproxy.com/check-ip")
driver.quit()

方法二:自定义扩展方案

在不希望承担 Selenium-wire 的 MITM(中间人)代理开销的高性能场景中,动态创建一个临时 Chrome 扩展是业界标准做法。该扩展使用 chrome.proxy API 设置凭据。

import os
import zipfile
from selenium import webdriver

def create_proxy_extension(proxy_host, proxy_port, proxy_user, proxy_pass):
    manifest_json = """
    {
        "version": "1.0.0",
        "manifest_version": 2,
        "name": "GProxy Extension",
        "permissions": [
            "proxy",
            "tabs",
            "unlimitedStorage",
            "storage",
            "<all_urls>",
            "webRequest",
            "webRequestBlocking"
        ],
        "background": {
            "scripts": ["background.js"]
        },
        "minimum_chrome_version":"22.0.0"
    }
    """

    background_js = f"""
    var config = {{
            mode: "fixed_servers",
            rules: {{
              singleProxy: {{
                scheme: "http",
                host: "{proxy_host}",
                port: parseInt({proxy_port})
              }},
              bypassList: ["localhost"]
            }}
          }};

    chrome.proxy.settings.set({{value: config, scope: "regular"}}, function() {{}});

    chrome.webRequest.onAuthRequired.addListener(
                function(details) {{
                    return {{
                        authCredentials: {{
                            username: "{proxy_user}",
                            password: "{proxy_pass}"
                        }}
                    }};
                }},
                {{urls: ["<all_urls>"]}},
                ['blocking']
    );
    """
    
    extension_path = 'proxy_auth_plugin.zip'
    with zipfile.ZipFile(extension_path, 'w') as zp:
        zp.writestr("manifest.json", manifest_json)
        zp.writestr("background.js", background_js)
    
    return extension_path

# 具体实现
proxy_ext = create_proxy_extension("gw.gproxy.com", "10000", "my_user", "my_pass")
options = webdriver.ChromeOptions()
options.add_extension(proxy_ext)
driver = webdriver.Chrome(options=options)
如何在 Python 中为 Selenium 配置代理:完整指南

代理配置方法对比

选择哪种方法,取决于您的性能要求、代理类型(住宅代理还是数据中心代理),以及是否需要频繁轮换 IP。

方法 认证支持 性能 复杂度 适用场景
ChromeOptions 仅 IP 白名单 优秀 静态数据中心 IP
Selenium-wire 原生用户名/密码 中等(有额外开销) 快速原型、调试
自定义扩展 原生用户名/密码 优秀 生产级抓取
GProxy Backconnect 单一接入点 优秀 大规模 IP 轮换

高级代理管理:轮换与粘性会话

使用 GProxy 时,您通常要在轮换代理粘性会话之间做选择。了解如何在 Python 中实现它们,对于在结算流程或多步表单提交中保持会话连续性至关重要。

实现粘性会话

粘性会话可确保您的 Selenium 驱动实例发出的所有请求在设定时长内(例如 10 到 30 分钟)停留在同一个 IP 地址上。在 GProxy 中,这通常通过用户名字符串里的会话 ID 来实现。

# 使用 GProxy 住宅代理池的粘性会话示例
session_id = "session_82734"
proxy_user = f"user-customer_id-session-{session_id}"
# 然后在 Selenium-wire 或扩展配置中使用该用户名字符串

配合代理管理无头模式

在服务器端脚本中以无头模式(--headless)运行 Selenium 是常规做法。但无头 Chrome 有时会泄露您的真实 IP,或者无法加载扩展。如果您用扩展方式做认证,必须使用 Chrome 109+ 提供的新版无头模式,才能保证扩展被正确加载:

options.add_argument('--headless=new')

--headless=new 参数让浏览器环境更接近有界面的浏览器,从而提升代理认证的可靠性,并降低被高级反机器人脚本识别的概率。

常见代理问题排查

即使配置正确,Selenium 的代理方案仍可能出问题。以下是最常见的故障及其技术解决办法:

  • ProxyConnectionError:通常是端口填错,或防火墙拦截了到代理服务商的出站连接。请确认 10000 端口(或服务商指定的端口)已放行。
  • DNS 泄露:默认情况下 Selenium 仍可能通过本地 ISP 解析 DNS 查询。为避免这一点,尤其是在使用 SOCKS5 时,请确保浏览器被配置为通过代理执行 DNS 查询。
  • 加载缓慢:住宅代理天然比数据中心代理慢。如果性能至关重要且您没有遭遇激进的 IP 封禁,请使用 GProxy 的数据中心代理池。
  • 认证弹窗:如果出现登录弹窗,说明您的认证方式(扩展或 Selenium-wire)失败了,或者没有在第一次请求之前完成初始化。

关键要点

在 Selenium 中配置代理是一个分层的过程。简单的 IP 白名单代理可以通过命令行参数搞定,而带认证的住宅代理则需要自定义扩展或 Selenium-wire 这类更稳健的方案。

  • 使用 GProxy Backconnect:与其在 Python 代码里维护一份 10,000 个 IP 的清单,不如使用 GProxy 提供的单一 backconnect 接入点自动完成轮换。
  • 优先选择扩展方案:在生产环境中,Chrome 扩展方式优于 Selenium-wire,因为它不引入第二层代理,延迟更低。
  • 监控成功率:始终把 driver.get() 调用包在 try-except 中以捕获 WebDriverException,让脚本在某个代理节点失效时更换会话 ID 并重试。
support_agent
GProxy Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.