Zendriver代理与身份验证:设置与解决方案

Zendriver是nodriver的社区维护分支——修复速度更快,但仍存在相同的身份验证代理问题。以下是完整的代理设置、实际差异以及使用户:密码生效的解决方案。

zendriver代理的设置与nodriver完全相同——这既是好消息也是问题所在。zendriver(cdpdriver/zendriver项目)是nodriver的社区维护分支:一个异步优先、未检测的浏览器自动化框架,直接通过DevTools协议驱动Chrome,没有WebDriver。它的存在是因为nodriver的单一维护者很少合并外部修复,因此社区进行了分支以接受错误修复、添加功能并在GitHub上处理问题。它没有修复的是身份验证代理。本指南涵盖完整的代理设置、与nodriver的实际差异以及使user:pass生效的解决方案。

安装和基本代理设置

安装只需一行——pip install zendriver——API几乎与nodriver逐符号镜像,因此在移植脚本时import zendriver as zd通常是唯一的变化。未认证的代理通过browser_args,请求从代理IP退出:

import zendriver as zd

async def main():
    browser = await zd.start(
        browser_args=["--proxy-server=gate.quantumproxies.io:PORT"],
    )
    page = await browser.get("https://httpbin.org/ip")
    print(await page.get_content())   # shows the proxy exit IP
    await browser.stop()

zd.loop().run_until_complete(main())

这之所以有效是因为它只是一个Chrome标志。添加凭据——--proxy-server=http://USER:PASS@host:port——Chromium会静默丢弃USER:PASS@部分,代理回复407,并出现一个zendriver无法填充的本地登录对话框。这是Chrome的限制,而不是zendriver的错误,因此没有版本更新会使该标志接受密码。

zendriver代理身份验证问题

该问题在zendriver的问题中公开跟踪——一个功能请求线程(#10)和一个专门的“带身份验证的代理”问题(#208)——这本身就是一个值得注意的差异:在nodriver上,同样的问题被埋在一个讨论中,维护者回答一次就不再理会。问题#10上的一位用户直言不讳地总结了现状:代理服务器选项没有身份验证方式,因此他们使用代理扩展,效果很好。这是经过实地验证的共识,直接指向nodriver用户依赖的相同三个修复。

修复1:IP白名单(最简单)

如果您的工作在具有稳定公共IP的机器上运行,则完全跳过凭据。在您的提供商仪表板中注册出口IP,网关通过源地址对您进行身份验证——zendriver代码保持上述简单的--proxy-server片段,没有身份验证逻辑。每个QuantumProxies计划都支持IP白名单和用户:密码,这使得当您的IP固定时,这是默认建议。唯一的限制是它对机器而不是脚本进行身份验证,因此NAT后的临时运行器和容器需要以下两种方法之一。

nodriver和zendriver的对比显示共享的CDP架构和代理身份验证问题,但维护模式不同
zendriver保留了nodriver的隐身和API,同时添加了一个开放的问题跟踪器——然而,代理身份验证问题仍然未变。

修复2:通过CDP回答挑战

因为zendriver以与nodriver相同的方式暴露了DevTools协议,您可以在进程中拦截身份验证挑战:注册RequestPausedAuthRequired处理程序,然后启用Fetch域,设置handle_auth_requests=True并回复continue_with_auth。两个不明显的规则与nodriver相同——在启用域之前添加处理程序,并使用asyncio.create_task触发响应,以便等待它们不会导致循环死锁:

import asyncio
import zendriver as zd

async def main():
    browser = await zd.start(browser_args=["--proxy-server=gate.quantumproxies.io:PORT"])
    tab = await browser.get("draft:,")            # blank tab first

    async def on_auth(event):
        asyncio.create_task(tab.send(zd.cdp.fetch.continue_with_auth(
            request_id=event.request_id,
            auth_challenge_response=zd.cdp.fetch.AuthChallengeResponse(
                response="ProvideCredentials", username="USER", password="PASS",
            ),
        )))

    async def on_request(event):
        asyncio.create_task(tab.send(
            zd.cdp.fetch.continue_request(request_id=event.request_id)))

    # handlers FIRST, then enable the domain
    tab.add_handler(zd.cdp.fetch.RequestPaused, on_request)
    tab.add_handler(zd.cdp.fetch.AuthRequired, on_auth)
    await tab.send(zd.cdp.fetch.enable(handle_auth_requests=True))

    page = await browser.get("https://httpbin.org/ip")
    await asyncio.sleep(3)
    print(await page.get_content())
    await browser.stop()

zd.loop().run_until_complete(main())

处理程序顺序为何重要以及出错时会发生什么的完整演练,请参阅我们的nodriver代理身份验证指南——机制是共享的,因此没有理由重复两次。

修复3:代理身份验证扩展和SOCKS5

问题#10推荐的路线是生成的Chrome扩展:Manifest V3清单加上设置代理并回答chrome.webRequest.onAuthRequired的工作程序,使用--load-extension--headless=new下加载。它可以处理任何类型的代理,包括SOCKS5,这很重要,因为经过身份验证的SOCKS5从未通过标志工作——Chromium没有为SOCKS5实现用户名/密码支持(Chromium bug 40829748)。SOCKS5的替代方案是一个本地中继,持有凭据并在127.0.0.1上提供无身份验证端点,详见代理中继指南。每个QuantumProxies计划都提供HTTP和SOCKS5端点,因此您通常可以通过使用HTTP来绕过整个问题,HTTP可以干净地处理基本身份验证。

与nodriver的实际差异

分支不是表面上的。在将nodriver、zendriver、Selenium和Playwright与现代反机器人系统对比的公开基准测试中,nodriver/zendriver家族在通过方面最强,zendriver由于携带未合并的上游修复而稍微领先。实际上,影响代理工作的差异是:一个活跃的问题跟踪器,问题得到分类,更稳定的发布节奏,可以每个会话启动的隔离浏览器上下文,以及从nodriver保留的内置便利功能。这些都没有解决身份验证问题——但这意味着修复到达时会更快,并且使zendriver成为运行多个并行会话的更简单的分支。对于在这些并发上下文中旋转和池化出口,我们关于代理池管理的笔记适用于zendriver,无论您是通过旋转代理路由还是为登录流固定粘性会话。

一个澄清:在docs.rs上也存在一个名为zendriver的独立Rust crate。它与这里讨论的Python分支无关——如果您在Python中进行抓取,pip install zendriver是您需要的。

zendriver代理身份验证流程:安装、使用代理标志启动、将IP列入白名单,或退回到CDP身份验证处理程序
当您的出口IP稳定时使用白名单;当不稳定时回答CDP挑战。无论哪种方式,用户:密码标志都是死胡同。

常见问题解答

如何在zendriver中使用代理?

在调用zendriver.start()时通过browser_args传递地址:browser_args=["--proxy-server=host:port"]。这会将所有流量路由到未认证的端点的代理。对于认证代理,您不能在标志中放置user:pass——将您的IP列入白名单,使用CDP Fetch.AuthRequired处理程序,或加载代理身份验证扩展。

zendriver支持认证代理吗?

没有内置参数——问题#10和#208中跟踪了这个缺口。Chromium忽略代理标志中的凭据,因此您需要通过其他方式进行身份验证:在提供商处进行IP白名单,在进程中回答挑战的CDP处理程序,生成的Chrome扩展,或持有凭据的本地中继。

nodriver和zendriver有什么区别?

zendriver是nodriver的社区维护分支,具有相同的CDP架构、隐身目标和API。区别在于维护:zendriver在GitHub上接受问题和拉取请求,发布未合并的上游错误修复,并更定期发布。代理身份验证在两者中表现相同——本指南中的修复适用于两者。

zendriver可以使用经过身份验证的SOCKS5代理吗?

不能通过标志,因为Chromium从未实现SOCKS5用户名/密码身份验证(Chromium bug 40829748),zendriver继承了这一点。使用代理身份验证扩展,运行添加凭据的本地中继,或将zendriver指向您的提供商的HTTP端点——HTTP基本代理身份验证在SOCKS5身份验证不起作用的地方可靠。

zendriver是今天构建的两个分支中更锋利的一个,但它给您带来了与nodriver相同的身份验证代理问题。当您的IP固定时使用白名单,当不固定时回答CDP挑战,并将扩展和中继作为备选方案。无论选择哪种方式,出口IP都起到了关键作用——在烧毁的数据中心地址上的维护分支仍然会被阻止。

为zendriver提供干净的住宅出口