Python 怎么过 Cloudflare 的那个点击?

用 playwright 的 chrome 和 edge 引擎的,似乎都过不去的,人工点击的目前。

47 个赞

前几天不是有个哥们发了puppeteer能过?试下?

3 个赞

selenium可以用
https://github.com/ultrafunkamsterdam/undetected-chromedriver

playwright不知道

53 个赞

我试试看

1 个赞

研究下,看着是设置了一堆参数,来模拟浏览器的。

1 个赞

同问蹲一个大佬

1 个赞

最简单就是selenium

可以用类似 DrissionPage 这种CDP协议实现的自动化框架

1 个赞

看着可行,需要调整大量代码,我得试试看的

首先去了解这个:

然后对应playwright版:
https://github.com/requireCool/stealth.min.js

最后来这儿检测:
https://bot.sannysoft.com/

2 个赞

我也看到这两个库的,前面那个 bypass 用的 puppeteer 也是这种逻辑跳过的,正在准备尝试这个不用大规模变更的方案的

看这个视频。

2 个赞

统一回复,断断续续折腾了几天的,终于用 python 的 DrissionPage 无头模式折腾出来了。

感谢各位大佬献计献策,其实我知道用 puppeteer 更加简单的样子。


2024.07.16

  1. 设置 UA 成为正常的 UA,避免 Headerless 的问题
  2. 设置一些参数,方便在 Linux 中启动起来

2024.07.26

修复了一下查找iframe的逻辑


代码

  1. 如果不需要 logger 的需要自行删除
  2. user_agent 传入本地浏览器内核的真实 ua
  3. user_data_path 可以不用传
  4. screencast 是为了方便debug,真实情况下可以删掉

async def solve_turnstile(logger: 'loguru.Logger', url: str, user_agent: str, user_data_path: str = None):
    import asyncio
    from DrissionPage import ChromiumPage, ChromiumOptions
    options = (
        ChromiumOptions()
        .auto_port()
        .headless()
        .incognito(True)
        .set_user_agent(user_agent)
        .set_argument('--guest')
        .set_argument('--no-sandbox')
        .set_argument('--disable-gpu')
    )
    if user_data_path:
        options.set_user_data_path(user_data_path)
    page = ChromiumPage(options)
    page.screencast.set_save_path('turnstile')
    page.screencast.set_mode.video_mode()
    page.screencast.start()
    page.get(url)
    logger.debug('waiting for turnstile')
    await asyncio.sleep(2)
    divs = page.eles('tag:div', timeout=10)
    iframe = None
    for div in divs:
        if div.shadow_root:
            iframe = div.shadow_root.ele(
                "xpath://iframe[starts-with(@src, 'https://challenges.cloudflare.com/')]",
                timeout=0
            )
            if iframe:
                break
            break
    body_element = iframe.ele('tag:body', timeout=10).shadow_root
    logger.debug('waiting for text:Verify you are human')
    verify_element = body_element.ele("text:Verify you are human", timeout=10)
    await asyncio.sleep(1)
    logger.debug('click verify')
    verify_element.offset(10, 10).click(by_js=False)
    logger.debug('waiting for deleted')
    verify_element.wait.deleted(timeout=10)
    await asyncio.sleep(1)
    page.screencast.stop()
    page.close()

8 个赞

专业贴,给赞

失效了

Matk

不会啊,我依旧可以用呢

额,只是为了持久化存储的,实际上可以不用设置的,没啥用

可以点击成功

学到了,mark一下