Selenium JavaScript配置Chrome带账号密码认证的代理失效
问题原因
Chrome 浏览器的 --proxy-server 启动参数原生不支持在代理地址中直接嵌入用户名、密码传递认证信息,这是你把认证信息拼接在代理地址后访问站点失败的核心原因。移除账号密码后弹出的认证窗口是Chrome的原生代理鉴权弹窗,手动输入信息后可正常访问符合代理的正常鉴权逻辑。
可行解决方案
方案1:使用Chrome扩展实现代理自动认证(稳定性最高,无弹窗)
这是生产环境最常用的实现方式,通过Chrome官方开放的扩展API完成代理配置和自动鉴权,不会弹出认证窗口。
- 新建一个空目录存放扩展文件,例如命名为
proxy-auth-ext,在目录内新建两个文件:manifest.json,扩展配置文件,内容如下:
{ "version": "1.0.0", "manifest_version": 2, "name": "Proxy Auto Auth", "permissions": [ "proxy", "tabs", "storage", "<all_urls>", "webRequest", "webRequestBlocking" ], "background": { "scripts": ["background.js"] } }background.js,代理配置和鉴权逻辑文件,替换成你自己的代理信息即可:
// 替换为实际代理IP、端口 const proxyConf = { mode: "fixed_servers", rules: { singleProxy: { scheme: "http", host: "你的代理IP地址", port: 代理端口数字 }, bypassList: ["localhost", "127.0.0.1"] } }; chrome.proxy.settings.set({value: proxyConf, scope: "regular"}, () => {}); // 自动填充代理认证信息 chrome.webRequest.onAuthRequired.addListener( () => ({ authCredentials: { username: "你的代理用户名", password: "你的代理密码" } }), {urls: ["<all_urls>"]}, ['blocking'] ); - 修改Selenium启动代码,直接加载该扩展目录即可,不需要再传
--proxy-server参数:const { Builder } = require('selenium-webdriver') const chrome = require('selenium-webdriver/chrome') const path = require('path') const option = new chrome.Options() // 加载刚才创建的扩展目录 option.addExtensions(path.resolve(__dirname, './proxy-auth-ext')) const driver = new Builder().forBrowser('chrome').setChromeOptions(option).build() driver.get('http://httpbin.org/ip') .then(() => console.log('DONE'))
方案2:监听鉴权弹窗自动填充(无需额外文件,稳定性一般)
如果不想创建扩展,可以在启动浏览器后监听原生鉴权弹窗,自动输入账号密码,缺点是启动时可能短暂闪过认证弹窗,偶发弹窗捕获失败的问题。
参考代码如下:
const { Builder, until } = require('selenium-webdriver') const chrome = require('selenium-webdriver/chrome') // 代理地址不要携带用户名密码 const PROXY = "你的代理IP:代理端口" const PROXY_USER = "你的代理用户名" const PROXY_PWD = "你的代理密码" const option = new chrome.Options().addArguments(`--proxy-server=http://${PROXY}`) const driver = new Builder().forBrowser('chrome').setChromeOptions(option).build() (async () => { await driver.get('http://httpbin.org/ip') // 等待用户名输入弹窗 await driver.wait(until.alertIsPresent(), 3000) let authAlert = await driver.switchTo().alert() await authAlert.sendKeys(PROXY_USER) await authAlert.accept() // 等待密码输入弹窗 await driver.wait(until.alertIsPresent(), 3000) authAlert = await driver.switchTo().alert() await authAlert.sendKeys(PROXY_PWD) await authAlert.accept() console.log('DONE') })()
注意事项
不要尝试将用户名密码直接拼接在--proxy-server参数的地址中,Chrome 59之后的版本已经完全禁用了这种传参方式,无论怎么调整格式都会直接报站点无法访问的错误,没有兼容解法。
内容的提问来源于stack exchange,提问作者Garda
相关产品推荐
相关产品推荐

