开始之前

  • Python 3 和 Selenium 4.32 或更新版本。安装包里自带 Selenium Manager,第一次运行时会下载匹配的驱动。
  • 运行脚本的机器上装有 Chrome 或 Firefox。
  • 从服务页面复制的 HOST、PORT、USERNAME 和 PASSWORD。

你的连接信息

登录控制台,打开你购买的服务。服务页面上会显示该服务的主机、端口、用户名和密码。ProxyPanda 没有一个统一的固定地址,所以每次都请从那里复制。指南中的代码使用下面这些占位符,请逐一替换成你自己的值。

HOST
该服务的代理地址,按服务页面上显示的原样填写。
PORT
要连接的端口。请和主机一起复制,因为不同服务的端口可能不同。
USERNAME
你的代理登录名。它与你登录控制台所用的邮箱是分开的。
PASSWORD
请完整复制。住宅代理在控制台中选择的选项会附加在密码末尾,凭记忆手动输入的密码会丢失这些选项。

把你用来连接的 IP 地址加入服务的白名单,就可以不用用户名和密码。这时代码里只需要 HOST 和 PORT。

示例都使用 HTTP,它可以通过加密隧道访问 https 网站。SOCKS5 同样可用:住宅代理的端口两种都接受,ISP 和数据中心代理在控制台里切换协议。

步骤

  1. 安装或升级 Selenium

    下面用到的 network 和 browsing_context 从 4.32 开始提供。更旧的版本在导入那一行就会报错,所以动手之前先确认版本号。

    terminal
    pip install -U selenium
    python -c "import selenium; print(selenium.__version__)"
  2. 地址写进参数,登录交给 add_auth_handler

    enable_bidi 会在经典协议之外再开一条 WebDriver BiDi 通道。--proxy-server 参数只写协议、主机和端口。随后 driver.network.add_auth_handler 会等待代理返回 407,并用你的凭据作答,对会话里的每个标签页都有效。

    check_ip.py
    from selenium import webdriver
    from selenium.webdriver.common.bidi.browsing_context import ReadinessState
    
    options = webdriver.ChromeOptions()
    options.enable_bidi = True
    options.add_argument("--proxy-server=http://HOST:PORT")
    
    driver = webdriver.Chrome(options=options)
    driver.network.add_auth_handler("USERNAME", "PASSWORD")
    
    driver.browsing_context.navigate(
        context=driver.current_window_handle,
        url="https://api.ipify.org",
        wait=ReadinessState.COMPLETE,
    )
    print(driver.find_element("tag name", "body").text)
    driver.quit()
  3. 用 browsing_context.navigate 打开第一个页面

    在 Chrome 中,经典的 driver.get 会在页面加载期间占住驱动,而回应登录也要用到这个驱动,两边互相等待,直到脚本超时。改用 BiDi 导航就能避开这个死锁。代理接受过一次登录之后,Chrome 会继续沿用,这个会话后面的普通 driver.get 也能正常工作。

  4. 在 Firefox 中做同样的检查

    Firefox 通过 Selenium 的 Proxy 对象接收代理,普通 HTTP 和 HTTPS 各写一项。它的 BiDi 实现能在普通 driver.get 的过程中完成登录,所以这个版本不需要特殊的导航方式。

    check_ip_firefox.py
    from selenium import webdriver
    from selenium.webdriver.common.proxy import Proxy
    
    options = webdriver.FirefoxOptions()
    options.enable_bidi = True
    options.proxy = Proxy({"httpProxy": "HOST:PORT", "sslProxy": "HOST:PORT"})
    
    driver = webdriver.Firefox(options=options)
    driver.network.add_auth_handler("USERNAME", "PASSWORD")
    
    driver.get("https://api.ipify.org")
    print(driver.find_element("tag name", "body").text)
    driver.quit()
  5. 在服务器上用无头模式运行

    创建驱动之前,Chrome 加上 options.add_argument("--headless=new"),Firefox 加上 options.add_argument("-headless")。其余代码不用改:有没有窗口,处理器都会回应代理。

轮换 IP 与粘性 IP

一个 Selenium 会话会打开很多连接:页面本身、脚本、图片。住宅代理选“随机 IP”时,这些连接可能从不同地址发出,网站会看到同一次访问来自好几个地方。脚本要登录,或要跨多个页面填写表单时,请选“粘性 IP”。

想以新身份重新开始,就退出驱动再新建一个。Cookie 会随之清空;在“随机 IP”模式下,新会话也会从另一个地址出发。

ISP 和数据中心 IP 在租期内不会变化,通过它打开的每个会话都显示同一个地址。

常见错误与解决办法

net::ERR_NO_SUPPORTED_PROXIES

--proxy-server 参数里写了 USERNAME:PASSWORD,Chrome 不接受这种写法。参数里只留 http://HOST:PORT,登录交给 add_auth_handler。

net::ERR_INVALID_AUTH_CREDENTIALS

Chrome 收到了代理的 407,却没有任何东西去回应。确认 add_auth_handler 在第一次导航之前就已调用。

Unable to find url to connect to from capabilities

缺少 options.enable_bidi = True,driver.network 没有 BiDi 通道可用。请在创建驱动之前把它设置在 options 上。

net::ERR_TOO_MANY_RETRIES

处理器发送了登录信息,代理却一再拒绝。用户名或密码有误或不完整,请从服务页面重新复制两者。

Timed out waiting for response to BiDi command,随后出现 ReadTimeoutError

Chrome 用 driver.get 打开了第一个页面,登录回应被它堵在后面。第一个页面请像第 3 步那样用 browsing_context.navigate 打开。

ModuleNotFoundError: No module named 'selenium.webdriver.common.bidi.browsing_context'

安装的 Selenium 早于 4.32。用 pip install -U selenium 升级即可。

选择哪条产品线

Selenium 驱动的是完整的浏览器,每张图片、每个脚本都算流量。网站接受服务器地址时,用数据中心 IP 跑测试、查后台最省钱。网站会检查网络来源时,用住宅代理加“粘性 IP”;某个配置每天都回到同一个账号时,选 ISP。

卡在某一步了?

把命令和报错贴到 Discord,记得先删掉密码。那里的人大多遇到过这些错误。

加入 Discorddiscord.gg/proxypanda
$5 起步去 Discord 问