g1879 / DrissionPage

Python based web automation tool. Powerful and elegant.
https://DrissionPage.cn/
BSD 3-Clause "New" or "Revised" License
8.35k stars 788 forks source link

It didnt work please help me #295

Open frkncnblt01 opened 4 months ago

frkncnblt01 commented 4 months ago

from DrissionPage import ChromiumPage

p = ChromiumPage() p.get('https://nowsecure.nl/') i = p.get_frame('@src^https://challenges.cloudflare.com/cdn-cgi') if i: i('.cb-i').click()

it is worked perfectly before today. what is the problem anyone help me ?

AnthraX1 commented 4 months ago

Cloudflare moved the iframe under a closed shadow root, which is difficult to get the contents.

frkncnblt01 commented 4 months ago

I understand. So what should I do, is there any other method you know?

AnthraX1 commented 4 months ago

Move mouse 120px left from the center of #turnstile-wrapper then click.

It's possible to get contents under shadowroot direcly using CDP command DOM.getDocument with parameter pierce=True. I checked the source https://github.com/g1879/DrissionPage/blob/b4f94caad033d6f14e2214bbb7514d8fd9d66c63/DrissionPage/_pages/chromium_base.py#L163 and it's left with the default value False.

frkncnblt01 commented 4 months ago

Moving mouse maybe works one script, if I run a lot of script is it possible ?

AnthraX1 commented 4 months ago

Moving mouse maybe works one script, if I run a lot of script is it possible ?

I haven't tried.

adryfish commented 4 months ago

I also encountered the same problem. Here is my solution:

wrapper = page.ele(".cf-turnstile-wrapper")
shadow_root = wrapper.shadow_root
iframe = shadow_root.ele("tag=iframe", timeout=15)
verify_element = iframe.ele("Verify you are human", timeout=25)
frkncnblt01 commented 4 months ago

After verify what do you do ? “.cb-i” and click right ?

jifeilong9 commented 4 months ago

我也遇到了同样的问题。这是我的解决方案:

wrapper = page.ele(".cf-turnstile-wrapper")
shadow_root = wrapper.shadow_root
iframe = shadow_root.ele("tag=iframe", timeout=15)
verify_element = iframe.ele("Verify you are human", timeout=25)

可以点了,但是现在好像加强了,不通过

frkncnblt01 commented 4 months ago

Yes it didnt work

AnthraX1 commented 4 months ago

我也遇到了同样的问题。这是我的解决方案:

wrapper = page.ele(".cf-turnstile-wrapper")
shadow_root = wrapper.shadow_root
iframe = shadow_root.ele("tag=iframe", timeout=15)
verify_element = iframe.ele("Verify you are human", timeout=25)

可以点了,但是现在好像加强了,不通过

need residential proxy. CF blocked all server IP ranges

jifeilong9 commented 4 months ago

我也遇到了同样的问题。这是我的解决方案:

wrapper = page.ele(".cf-turnstile-wrapper")
shadow_root = wrapper.shadow_root
iframe = shadow_root.ele("tag=iframe", timeout=15)
verify_element = iframe.ele("Verify you are human", timeout=25)

可以点了,但是现在好像加强了,不通过

need residential proxy. CF blocked all server IP ranges

应该不是,我等程序点失败了,我人工去点就可以,我怀疑是有新的行为分析

AnthraX1 commented 4 months ago

我也遇到了同样的问题。这是我的解决方案:

wrapper = page.ele(".cf-turnstile-wrapper")
shadow_root = wrapper.shadow_root
iframe = shadow_root.ele("tag=iframe", timeout=15)
verify_element = iframe.ele("Verify you are human", timeout=25)

可以点了,但是现在好像加强了,不通过

need residential proxy. CF blocked all server IP ranges

应该不是,我等程序点失败了,我人工去点就可以,我怀疑是有新的行为分析

Don't use .click(), I suspect there's some kind of timing and mouse tracking analysis.

After checkbox is detected, randomly wait a while using page.wait(0.01, 0.1), then use Actions to move mouse and click manually with random delay. For example:

from DrissionPage.common import Actions
actions=Actions(page)
actions.move_to("#turnstile-wrapper", duration=0.5).left(120).hold().wait(0.01, 0.15).release(). 

This worked for me.

g1879 commented 4 months ago

用这个试试pip install DrissionPage==4.1.0.0b2

liuphillpotts commented 4 months ago

我也遇到了同样的问题。这是我的解决方案:

wrapper = page.ele(".cf-turnstile-wrapper")
shadow_root = wrapper.shadow_root
iframe = shadow_root.ele("tag=iframe", timeout=15)
verify_element = iframe.ele("Verify you are human", timeout=25)

可以点了,但是现在好像加强了,不通过

need residential proxy. CF blocked all server IP ranges

应该不是,我等程序点失败了,我人工去点就可以,我怀疑是有新的行为分析

Don't use .click(), I suspect there's some kind of timing and mouse tracking analysis.

After checkbox is detected, randomly wait a while using page.wait(0.01, 0.1), then use Actions to move mouse and click manually with random delay. For example:

from DrissionPage.common import Actions
actions=Actions(page)
actions.move_to("#turnstile-wrapper", duration=0.5).left(120).hold().wait(0.01, 0.15).release(). 

This worked for me.

I tested one, it's useful, it should be mouse behavior detection. Wait for me to test it on a large scale

AnthraX1 commented 4 months ago

我也遇到了同样的问题。这是我的解决方案:

wrapper = page.ele(".cf-turnstile-wrapper")
shadow_root = wrapper.shadow_root
iframe = shadow_root.ele("tag=iframe", timeout=15)
verify_element = iframe.ele("Verify you are human", timeout=25)

可以点了,但是现在好像加强了,不通过

need residential proxy. CF blocked all server IP ranges

应该不是,我等程序点失败了,我人工去点就可以,我怀疑是有新的行为分析

Don't use .click(), I suspect there's some kind of timing and mouse tracking analysis. After checkbox is detected, randomly wait a while using page.wait(0.01, 0.1), then use Actions to move mouse and click manually with random delay. For example:

from DrissionPage.common import Actions
actions=Actions(page)
actions.move_to("#turnstile-wrapper", duration=0.5).left(120).hold().wait(0.01, 0.15).release(). 

This worked for me.

I tested one, it's useful, it should be mouse behavior detection. Wait for me to test it on a large scale

It's also easy to simulate human mouse movements by adding random sideways movements with offset_x, offset_y and non-uniform speed by adjusting the duration parameter randomly

adryfish commented 4 months ago

click() 方法无法触发成功,而手动点击可以成功的原因是,click() 方法触发的事件中,ClientX, ClientY和ScreenX, ScreenY 属性相同,而手动点击触发的事件不同。

frkncnblt01 commented 4 months ago

我也遇到了同样的问题。这是我的解决方案:

wrapper = page.ele(".cf-turnstile-wrapper")
shadow_root = wrapper.shadow_root
iframe = shadow_root.ele("tag=iframe", timeout=15)
verify_element = iframe.ele("Verify you are human", timeout=25)

可以点了,但是现在好像加强了,不通过

need residential proxy. CF blocked all server IP ranges

应该不是,我等程序点失败了,我人工去点就可以,我怀疑是有新的行为分析

Don't use .click(), I suspect there's some kind of timing and mouse tracking analysis. After checkbox is detected, randomly wait a while using page.wait(0.01, 0.1), then use Actions to move mouse and click manually with random delay. For example:

from DrissionPage.common import Actions
actions=Actions(page)
actions.move_to("#turnstile-wrapper", duration=0.5).left(120).hold().wait(0.01, 0.15).release(). 

This worked for me.

I tested one, it's useful, it should be mouse behavior detection. Wait for me to test it on a large scale

Could you write the full code ?

frkncnblt01 commented 4 months ago

用这个试试pip install DrissionPage==4.1.0.0b2

Ok. The other things is same right ? Like .cb-i and click

liuphillpotts commented 4 months ago

我也遇到了同样的问题。这是我的解决方案:

wrapper = page.ele(".cf-turnstile-wrapper")
shadow_root = wrapper.shadow_root
iframe = shadow_root.ele("tag=iframe", timeout=15)
verify_element = iframe.ele("Verify you are human", timeout=25)

可以点了,但是现在好像加强了,不通过

need residential proxy. CF blocked all server IP ranges

应该不是,我等程序点失败了,我人工去点就可以,我怀疑是有新的行为分析

Don't use .click(), I suspect there's some kind of timing and mouse tracking analysis. After checkbox is detected, randomly wait a while using page.wait(0.01, 0.1), then use Actions to move mouse and click manually with random delay. For example:

from DrissionPage.common import Actions
actions=Actions(page)
actions.move_to("#turnstile-wrapper", duration=0.5).left(120).hold().wait(0.01, 0.15).release(). 

This worked for me.

I tested one, it's useful, it should be mouse behavior detection. Wait for me to test it on a large scale

It's also easy to simulate human mouse movements by adding random sideways movements with offset_x, offset_y and non-uniform speed by adjusting the duration parameter randomly

I tested a dozen fingerprint browsers and found that this solution could not skip them properly, only occasionally skipping one or two.

frkncnblt01 commented 4 months ago

我也遇到了同样的问题。这是我的解决方案:

wrapper = page.ele(".cf-turnstile-wrapper")
shadow_root = wrapper.shadow_root
iframe = shadow_root.ele("tag=iframe", timeout=15)
verify_element = iframe.ele("Verify you are human", timeout=25)

可以点了,但是现在好像加强了,不通过

need residential proxy. CF blocked all server IP ranges

应该不是,我等程序点失败了,我人工去点就可以,我怀疑是有新的行为分析

Don't use .click(), I suspect there's some kind of timing and mouse tracking analysis. After checkbox is detected, randomly wait a while using page.wait(0.01, 0.1), then use Actions to move mouse and click manually with random delay. For example:

from DrissionPage.common import Actions
actions=Actions(page)
actions.move_to("#turnstile-wrapper", duration=0.5).left(120).hold().wait(0.01, 0.15).release(). 

This worked for me.

I tested one, it's useful, it should be mouse behavior detection. Wait for me to test it on a large scale

It's also easy to simulate human mouse movements by adding random sideways movements with offset_x, offset_y and non-uniform speed by adjusting the duration parameter randomly

I tested a dozen fingerprint browsers and found that this solution could not skip them properly, only occasionally skipping one or two.

It didnt work for me, I test one or two but didnt work any of them

g1879 commented 4 months ago

用这个试试pip install DrissionPage==4.1.0.0b2

Ok. The other things is same right ? Like .cb-i and click

cf页面有变化,根据新页面修改一下就可以。

liuphillpotts commented 4 months ago

我也遇到了同样的问题。这是我的解决方案:

wrapper = page.ele(".cf-turnstile-wrapper")
shadow_root = wrapper.shadow_root
iframe = shadow_root.ele("tag=iframe", timeout=15)
verify_element = iframe.ele("Verify you are human", timeout=25)

可以点了,但是现在好像加强了,不通过

need residential proxy. CF blocked all server IP ranges

应该不是,我等程序点失败了,我人工去点就可以,我怀疑是有新的行为分析

Don't use .click(), I suspect there's some kind of timing and mouse tracking analysis. After checkbox is detected, randomly wait a while using page.wait(0.01, 0.1), then use Actions to move mouse and click manually with random delay. For example:

from DrissionPage.common import Actions
actions=Actions(page)
actions.move_to("#turnstile-wrapper", duration=0.5).left(120).hold().wait(0.01, 0.15).release(). 

This worked for me.

I tested one, it's useful, it should be mouse behavior detection. Wait for me to test it on a large scale

It's also easy to simulate human mouse movements by adding random sideways movements with offset_x, offset_y and non-uniform speed by adjusting the duration parameter randomly

I tested a dozen fingerprint browsers and found that this solution could not skip them properly, only occasionally skipping one or two.

It didnt work for me, I test one or two but didnt work any of them

import pyautogui try: cloudflare5s_coordinates = tab.ele(".cf-turnstile-wrapper") time.sleep(1) cloudflare5s_coordinates = cloudflare5s_coordinates.rect.screen_midpoint tab.wait(1) with file_lock: pyautogui.moveTo(cloudflare5s_coordinates ) tab.wait(0.1, 3) pyautogui.click() except: pass I can only use this method, which can be skipped after testing, but the disadvantage of this method is also obvious, multiple browsers share the same mouse. It is impossible to use it on a larger scale

AnthraX1 commented 4 months ago

我也遇到了同样的问题。这是我的解决方案:

wrapper = page.ele(".cf-turnstile-wrapper")
shadow_root = wrapper.shadow_root
iframe = shadow_root.ele("tag=iframe", timeout=15)
verify_element = iframe.ele("Verify you are human", timeout=25)

可以点了,但是现在好像加强了,不通过

need residential proxy. CF blocked all server IP ranges需要住宅代理。CF 阻止了所有服务器 IP 范围

应该不是,我等程序点失败了,我人工去点就可以,我怀疑是有新的行为分析

Don't use .click(), I suspect there's some kind of timing and mouse tracking analysis.不要使用 .click(),我怀疑有某种计时和鼠标跟踪分析。 After checkbox is detected, randomly wait a while using page.wait(0.01, 0.1), then use Actions to move mouse and click manually with random delay. For example:检测到复选框后,使用 page.wait(0.01, 0.1) 随机等待一段时间,然后使用动作移动鼠标并随机延迟手动单击。例如:

from DrissionPage.common import Actions
actions=Actions(page)
actions.move_to("#turnstile-wrapper", duration=0.5).left(120).hold().wait(0.01, 0.15).release(). 

This worked for me.这对我有用。

I tested one, it's useful, it should be mouse behavior detection. Wait for me to test it on a large scale我测试了一个,它很有用,它应该是鼠标行为检测。等我大规模测试

It's also easy to simulate human mouse movements by adding random sideways movements with offset_x, offset_y and non-uniform speed by adjusting the duration parameter randomly通过随机调整持续时间参数,添加具有offset_x、offset_y和非均匀速度的随机横向运动,也很容易模拟人类鼠标运动

I tested a dozen fingerprint browsers and found that this solution could not skip them properly, only occasionally skipping one or two.我测试了十几个指纹浏览器,发现这个解决方案无法正确跳过它们,只是偶尔跳过一两个。

It didnt work for me, I test one or two but didnt work any of them它对我不起作用,我测试了一两个,但没有一个有效 import pyautogui try: cloudflare5s_coordinates = tab.ele(".cf-turnstile-wrapper") time.sleep(1) cloudflare5s_coordinates = cloudflare5s_coordinates.rect.screen_midpoint tab.wait(1) with file_lock: pyautogui.moveTo(cloudflare5s_coordinates ) tab.wait(0.1, 3) pyautogui.click() except: pass I can only use this method, which can be skipped after testing, but the disadvantage of this method is also obvious, multiple browsers share the same mouse. It is impossible to use it on a larger scale

I think @adryfish is right. CF added new checks about the mouse coordinates too. https://github.com/g1879/DrissionPage/issues/295#issuecomment-2217250775 In his llm-web-api repo he used pyautogui to simulate click: https://github.com/adryfish/llm-web-api/commit/f3211a8ce547c0205dedeb9f3ad420aed8293f7a

I don't know what you are crawling but normally after you pass the CF turnstile check, the cookies could last at least 24 hours unless you are hitting registration or login pages.

lexburner commented 4 months ago

兄弟们太给力了,遇到了同样的问题,看起来是 cloudflare 最近才加强的校验?

lexburner commented 4 months ago

用这个试试pip install DrissionPage==4.1.0.0b2

Ok. The other things is same right ? Like .cb-i and click

cf页面有变化,根据新页面修改一下就可以。

已更新最新的版本,能够点击,但会提示 Failure,看起来没有通过 cf 的人机检测。

我的测试代码如下,破解是 https://core.particle.network/cloudflare.html 这个网址,这个网站也是最近才改版的,多了一个 cf-turnstile-wrapper,包了一层 shadow-root 的 iframe,通过 pip install DrissionPage==4.1.0.0b2 版本也是点击后 Failure。尝试使用鼠标点击,可以通过,提示 Success,感觉应该是模拟了鼠标的移动轨迹或者坐标之类的行为,期待新的解决方案

import time
from DrissionPage import ChromiumPage
from DrissionPage import ChromiumOptions
from DrissionPage.common import Actions

class LocalSovlerCF:
    def __init__(self):
        co = ChromiumOptions()
        page = ChromiumPage(co)
        page.get('https://core.particle.network/cloudflare.html')
        self.page = page

    def capsolver(self):
        cf_wrapper = self.page.ele('.cf-turnstile-wrapper')
        cf_iframe = None
        while True:
            try:
                shadow_root = cf_wrapper.shadow_root
                cf_iframe = shadow_root.ele("tag=iframe",timeout=3)
                break
            except:
                time.sleep(1)
        try:
            tokenDiv = self.page.ele('#turnstile-token', timeout=3)
            return tokenDiv.text
        except:
            print('need to click')
        time.sleep(3)
        try:
            verify_element = cf_iframe.ele("Verify you are human", timeout=5)
            verify_element.click()
        except:
            print(f'click Error')
            time.sleep(1)
        time.sleep(3)
        try:
            tokenDiv = self.page.ele('#turnstile-token', timeout=3)
            result = tokenDiv.text
            self.page.refresh()
            return result
        except Exception as e:
            print(f'{e}')
            return None

    def close(self):
        self.page.quit()

def main():
    lcoal_resovler = LocalSovlerCF()
    lcoal_resovler.capsolver()

if __name__ == '__main__':
    main()
liuphillpotts commented 4 months ago

用这个试试pip install DrissionPage==4.1.0.0b2

Ok. The other things is same right ? Like .cb-i and click

cf页面有变化,根据新页面修改一下就可以。

已更新最新的版本,能够点击,但会提示 Failure,看起来没有通过 cf 的人机检测。

我的测试代码如下,破解是 https://core.particle.network/cloudflare.html 这个网址,这个网站也是最近才改版的,多了一个 cf-turnstile-wrapper,包了一层 shadow-root 的 iframe,通过 pip install DrissionPage==4.1.0.0b2 版本也是点击后 Failure。尝试使用鼠标点击,可以通过,提示 Success,感觉应该是模拟了鼠标的移动轨迹或者坐标之类的行为,期待新的解决方案

import time
from DrissionPage import ChromiumPage
from DrissionPage import ChromiumOptions
from DrissionPage.common import Actions

class LocalSovlerCF:
    def __init__(self):
        co = ChromiumOptions()
        page = ChromiumPage(co)
        page.get('https://core.particle.network/cloudflare.html')
        self.page = page

    def capsolver(self):
        cf_wrapper = self.page.ele('.cf-turnstile-wrapper')
        cf_iframe = None
        while True:
            try:
                shadow_root = cf_wrapper.shadow_root
                cf_iframe = shadow_root.ele("tag=iframe",timeout=3)
                break
            except:
                time.sleep(1)
        try:
            tokenDiv = self.page.ele('#turnstile-token', timeout=3)
            return tokenDiv.text
        except:
            print('need to click')
        time.sleep(3)
        try:
            verify_element = cf_iframe.ele("Verify you are human", timeout=5)
            verify_element.click()
        except:
            print(f'click Error')
            time.sleep(1)
        time.sleep(3)
        try:
            tokenDiv = self.page.ele('#turnstile-token', timeout=3)
            result = tokenDiv.text
            self.page.refresh()
            return result
        except Exception as e:
            print(f'{e}')
            return None

    def close(self):
        self.page.quit()

def main():
    lcoal_resovler = LocalSovlerCF()
    lcoal_resovler.capsolver()

if __name__ == '__main__':
    main()
cf_iframe = shadow_root.ele("tag=iframe",timeout=3)

为什么我执行的时候这一行一直提示错误的,我检测了下代码也没问题

         tab = page.new_tab()
        tab.get('https://core.particle.network/cloudflare.html')
        time.sleep(8)
        wrapper = tab.ele(".cf-turnstile-wrapper")
        shadow_root = cf_wrapper.shadow_root
        iframe = shadow_root.ele("tag=iframe", timeout=3)
        verify_element = iframe.ele("Verify you are human", timeout=3)
        verify_element.click()

错误:args: {'locator': 'xpath:./ancestor:*[1]",'index': 1}

Tspm1eca commented 4 months ago

用这个试试pip install DrissionPage==4.1.0.0b2

能够点击,但不是住宅ip的话,会失败自动刷新页面

jifeilong9 commented 4 months ago

click() 方法无法触发成功,而手动点击可以成功的原因是,click() 方法触发的事件中,ClientX, ClientY和ScreenX, ScreenY 属性相同,而手动点击触发的事件不同。

大佬,你是如果处理的

adryfish commented 4 months ago

click() 方法无法触发成功,而手动点击可以成功的原因是,click() 方法触发的事件中,ClientX, ClientY和ScreenX, ScreenY 属性相同,而手动点击触发的事件不同。

大佬,你是如果处理的

这个是我的解决方案,获取坐标,使用pyautogui点击。注意在图形界面上PageX,和PageY的获取可能有问题,要加上--start-fullscreen启动参数。NO GUI的话加上--start-maximized启动参数

            wrapper = self.page.ele(".cf-turnstile-wrapper")
            shadow_root = wrapper.shadow_root
            iframe = shadow_root.ele("tag=iframe", timeout=15)
            verify_element = iframe.ele("Verify you are human", timeout=25)
            time.sleep(random.uniform(2, 5))

            # 2024-07-05
            # 直接在element上执行click(通过CDP协议)无法通过cloudflare challenge
            # 原因:
            # CDP命令执行的event中client_x, client_y与screen_x, screen_y是一样的,而手动点击触发的事件两者是不一样的,所以无法使用CDP模拟出鼠标点击通过验证
            # 解决方法:
            # 先获取点击的坐标,使用pyautogui模拟鼠标点击
            # CDP参考 https://chromedevtools.github.io/devtools-protocol/tot/Input/
            # verify_element.click()
            def generate_biased_random(n):
                weights = [min(i, n - i + 1) for i in range(1, n + 1)]
                return random.choices(range(1, n + 1), weights=weights)[0]

            screen_x, screen_y = verify_element.rect.screen_location
            page_x, page_y = self.page.rect.page_location
            width, height = verify_element.rect.size
            offset_x, offset_y = generate_biased_random(
                int(width - 1)
            ), generate_biased_random(int(height - 1))

            click_x, click_y = (
                screen_x + page_x + offset_x,
                screen_y + page_y + offset_y,
            )

            logger.info(
                f"[CloudflareBypass.try_to_click_challenge] Screen point [{screen_x}, {screen_y}]"
            )
            logger.info(
                f"[CloudflareBypass.try_to_click_challenge] Page point[{page_x}, {page_y}]"
            )
            logger.info(
                f"[CloudflareBypass.try_to_click_challenge] Click point [{click_x}, {click_y}]"
            )
            pyautogui.moveTo(
                click_x, click_y, duration=0.5, tween=pyautogui.easeInElastic
            )
            pyautogui.click()
            self.page.wait.load_start(timeout=20)
jifeilong9 commented 4 months ago

click() 方法无法触发成功,而手动点击可以成功的原因是,click() 方法触发的事件中,ClientX, ClientY和ScreenX, ScreenY 属性相同,而手动点击触发的事件不同。

大佬,你是如果处理的

这个是我的解决方案,获取坐标,使用pyautogui点击。注意在图形界面上PageX,和PageY的获取可能有问题,要加上--start-fullscreen启动参数。NO GUI的话加上--start-maximized启动参数

            wrapper = self.page.ele(".cf-turnstile-wrapper")
            shadow_root = wrapper.shadow_root
            iframe = shadow_root.ele("tag=iframe", timeout=15)
            verify_element = iframe.ele("Verify you are human", timeout=25)
            time.sleep(random.uniform(2, 5))

            # 2024-07-05
            # 直接在element上执行click(通过CDP协议)无法通过cloudflare challenge
            # 原因:
            # CDP命令执行的event中client_x, client_y与screen_x, screen_y是一样的,而手动点击触发的事件两者是不一样的,所以无法使用CDP模拟出鼠标点击通过验证
            # 解决方法:
            # 先获取点击的坐标,使用pyautogui模拟鼠标点击
            # CDP参考 https://chromedevtools.github.io/devtools-protocol/tot/Input/
            # verify_element.click()
            def generate_biased_random(n):
                weights = [min(i, n - i + 1) for i in range(1, n + 1)]
                return random.choices(range(1, n + 1), weights=weights)[0]

            screen_x, screen_y = verify_element.rect.screen_location
            page_x, page_y = self.page.rect.page_location
            width, height = verify_element.rect.size
            offset_x, offset_y = generate_biased_random(
                int(width - 1)
            ), generate_biased_random(int(height - 1))

            click_x, click_y = (
                screen_x + page_x + offset_x,
                screen_y + page_y + offset_y,
            )

            logger.info(
                f"[CloudflareBypass.try_to_click_challenge] Screen point [{screen_x}, {screen_y}]"
            )
            logger.info(
                f"[CloudflareBypass.try_to_click_challenge] Page point[{page_x}, {page_y}]"
            )
            logger.info(
                f"[CloudflareBypass.try_to_click_challenge] Click point [{click_x}, {click_y}]"
            )
            pyautogui.moveTo(
                click_x, click_y, duration=0.5, tween=pyautogui.easeInElastic
            )
            pyautogui.click()
            self.page.wait.load_start(timeout=20)

可以了感谢大佬

lexburner commented 4 months ago

使用 pyautogui 的确可以处理,我也测试成功了,但不算是最终解决方案,没法同时操作很多窗口,而且会占用鼠标

lexburner commented 4 months ago

用这个试试pip install DrissionPage==4.1.0.0b2

Ok. The other things is same right ? Like .cb-i and click

cf页面有变化,根据新页面修改一下就可以。

已更新最新的版本,能够点击,但会提示 Failure,看起来没有通过 cf 的人机检测。 我的测试代码如下,破解是 https://core.particle.network/cloudflare.html 这个网址,这个网站也是最近才改版的,多了一个 cf-turnstile-wrapper,包了一层 shadow-root 的 iframe,通过 pip install DrissionPage==4.1.0.0b2 版本也是点击后 Failure。尝试使用鼠标点击,可以通过,提示 Success,感觉应该是模拟了鼠标的移动轨迹或者坐标之类的行为,期待新的解决方案

import time
from DrissionPage import ChromiumPage
from DrissionPage import ChromiumOptions
from DrissionPage.common import Actions

class LocalSovlerCF:
    def __init__(self):
        co = ChromiumOptions()
        page = ChromiumPage(co)
        page.get('https://core.particle.network/cloudflare.html')
        self.page = page

    def capsolver(self):
        cf_wrapper = self.page.ele('.cf-turnstile-wrapper')
        cf_iframe = None
        while True:
            try:
                shadow_root = cf_wrapper.shadow_root
                cf_iframe = shadow_root.ele("tag=iframe",timeout=3)
                break
            except:
                time.sleep(1)
        try:
            tokenDiv = self.page.ele('#turnstile-token', timeout=3)
            return tokenDiv.text
        except:
            print('need to click')
        time.sleep(3)
        try:
            verify_element = cf_iframe.ele("Verify you are human", timeout=5)
            verify_element.click()
        except:
            print(f'click Error')
            time.sleep(1)
        time.sleep(3)
        try:
            tokenDiv = self.page.ele('#turnstile-token', timeout=3)
            result = tokenDiv.text
            self.page.refresh()
            return result
        except Exception as e:
            print(f'{e}')
            return None

    def close(self):
        self.page.quit()

def main():
    lcoal_resovler = LocalSovlerCF()
    lcoal_resovler.capsolver()

if __name__ == '__main__':
    main()
cf_iframe = shadow_root.ele("tag=iframe",timeout=3)

为什么我执行的时候这一行一直提示错误的,我检测了下代码也没问题

         tab = page.new_tab()
        tab.get('https://core.particle.network/cloudflare.html')
        time.sleep(8)
        wrapper = tab.ele(".cf-turnstile-wrapper")
        shadow_root = cf_wrapper.shadow_root
        iframe = shadow_root.ele("tag=iframe", timeout=3)
        verify_element = iframe.ele("Verify you are human", timeout=3)
        verify_element.click()

错误:args: {'locator': 'xpath:./ancestor:*[1]",'index': 1}

shadow_root 加载可能需要时间,你搞个 try except 等待获取到 shadow_root 完整的元素不报错了,再继续往下执行试试

AnthraX1 commented 4 months ago

I wrote something to hook addEventListener() to modify screenX, screenY returned by the event. It'll add random int between (0,200) to both values to make them look real.

function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function modifyClickEvent(event) {
    if (!event._isModified) {
        // Save original values only if not already saved
        event._screenX = event.screenX;
        event._screenY = event.screenY;

        // Define properties only once
        Object.defineProperty(event, 'screenX', {
            get: function() {
                return this._screenX + getRandomInt(0, 200);
            }
        });
        Object.defineProperty(event, 'screenY', {
            get: function() {
                return this._screenY + getRandomInt(0, 200);
            }
        });

        // Mark event as modified
        event._isModified = true;
    }
}

// Store the original addEventListener method
const originalAddEventListener = EventTarget.prototype.addEventListener;

// Override the addEventListener method
EventTarget.prototype.addEventListener = function(type, listener, options) {
    if (type === 'click') {
        const wrappedListener = function(event) {
            // Modify the click event properties
            modifyClickEvent(event);

            // Call the original listener with the modified event
            listener.call(this, event);
        };
        // Call the original addEventListener with the wrapped listener
        originalAddEventListener.call(this, type, wrappedListener, options);
    } else {
        // Call the original addEventListener for other event types
        originalAddEventListener.call(this, type, listener, options);
    }
};

Use page.add_init_js() to inject this script into the page before calling page.get() I think CF also listens to mousedown and mouseup so you'll need to hook those too. I haven't tested the above method yet because turnstile never blocked me for simulated click(). I was not using headless mode and had fake display size set to 1680x1050

lexburner commented 4 months ago

function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }

function modifyClickEvent(event) { if (!event._isModified) { // Save original values only if not already saved event._screenX = event.screenX; event._screenY = event.screenY;

    // Define properties only once
    Object.defineProperty(event, 'screenX', {
        get: function() {
            return this._screenX + getRandomInt(0, 200);
        }
    });
    Object.defineProperty(event, 'screenY', {
        get: function() {
            return this._screenY + getRandomInt(0, 200);
        }
    });

    // Mark event as modified
    event._isModified = true;
}

}

// Store the original addEventListener method const originalAddEventListener = EventTarget.prototype.addEventListener;

// Override the addEventListener method EventTarget.prototype.addEventListener = function(type, listener, options) { if (type === 'click') { const wrappedListener = function(event) { // Modify the click event properties modifyClickEvent(event);

        // Call the original listener with the modified event
        listener.call(this, event);
    };
    // Call the original addEventListener with the wrapped listener
    originalAddEventListener.call(this, type, wrappedListener, options);
} else {
    // Call the original addEventListener for other event types
    originalAddEventListener.call(this, type, listener, options);
}

};

good job bro! it works for me!

sjn4048 commented 4 months ago

在使用上面方法时,发现无法在iframe中找到Verify的元素,是因为我的姿势不对,还是cf这两天又更新了?使用的版本是4.1.0.0b2,也试过b10,效果一致。求助 @lexburner @adryfish @jifeilong9

from DrissionPage import ChromiumPage

page = ChromiumPage() page.get('https://core.particle.network/cloudflare.html')

wrapper = page.ele(".cf-turnstile-wrapper") shadow_root = wrapper.shadow_root iframe = shadow_root.ele("tag=iframe", timeout=15) verify_element = iframe.ele("Verify you are human", timeout=25) # <--- 这行无法获取到元素,如果使用iframe.html,里边也没有元素

towenjian commented 4 months ago

在使用上面方法时,发现无法在iframe中找到Verify的元素,是因为我的姿势不对,还是cf这两天又更新了?使用的版本是4.1.0.0b2,也试过b10,效果一致。求助 @lexburner @adryfish @jifeilong9

from DrissionPage import ChromiumPage

page = ChromiumPage() page.get('https://core.particle.network/cloudflare.html')

wrapper = page.ele(".cf-turnstile-wrapper") shadow_root = wrapper.shadow_root iframe = shadow_root.ele("tag=iframe", timeout=15) verify_element = iframe.ele("Verify you are human", timeout=25) # <--- 这行无法获取到元素,如果使用iframe.html,里边也没有元素

bde = (
b
.ele(".cf-turnstile-wrapper", timeout=10)
.shadow_root
.ele("tag:iframe", timeout=10)
.ele('tag:body', timeout=10)
.shadow_root
)
ve = bde.ele("text:Verify you are human", timeout=10)

试试这个

jifeilong9 commented 4 months ago

在使用上面方法时,发现无法在iframe中找到Verify的元素,是因为我的姿势不对,还是cf这两天又更新了?使用的版本是4.1.0.0b2,也试过b10,效果一致。求助 @lexburner @adryfish @jifeilong9

from DrissionPage import ChromiumPage

page = ChromiumPage() page.get('https://core.particle.network/cloudflare.html')

wrapper = page.ele(".cf-turnstile-wrapper") shadow_root = wrapper.shadow_root iframe = shadow_root.ele("tag=iframe", timeout=15) verify_element = iframe.ele("Verify you are human", timeout=25) # <--- 这行无法获取到元素,如果使用iframe.html,里边也没有元素

.cf-turnstile-wrapper已经取不到了我换成了@style=border: 0px; margin: 0px; padding: 0px;可以取到,但是点击失败,我使用pyautogui可以了

johnyttt commented 4 months ago

Guys, do try to remove this --blink-settings=imagesEnabled=false flag if you have it before trying more complicated ideas.

Was trying to figure out why my scraped got Failure when clicking on CF turnstile checkbox and narrowed it down to this flag, can get Success with DrissionPage build-in click() after that.

riruigit commented 3 months ago

Guys, do try to remove this --blink-settings=imagesEnabled=false flag if you have it before trying more complicated ideas.

Was trying to figure out why my scraped got Failure when clicking on CF turnstile checkbox and narrowed it down to this flag, can get Success with DrissionPage build-in click() after that.

Hello, I'm still not sure how to operate. Could you show me some of your code?

riruigit commented 3 months ago

Guys, do try to remove this --blink-settings=imagesEnabled=false flag if you have it before trying more complicated ideas.

Was trying to figure out why my scraped got Failure when clicking on CF turnstile checkbox and narrowed it down to this flag, can get Success with DrissionPage build-in click() after that.

test URL:https://core.particle.network/cloudflare.html。 thank you very much

SoraRoseous commented 1 month ago

I wrote something to hook addEventListener() to modify screenX, screenY returned by the event. It'll add random int between (0,200) to both values to make them look real.

function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function modifyClickEvent(event) {
    if (!event._isModified) {
        // Save original values only if not already saved
        event._screenX = event.screenX;
        event._screenY = event.screenY;

        // Define properties only once
        Object.defineProperty(event, 'screenX', {
            get: function() {
                return this._screenX + getRandomInt(0, 200);
            }
        });
        Object.defineProperty(event, 'screenY', {
            get: function() {
                return this._screenY + getRandomInt(0, 200);
            }
        });

        // Mark event as modified
        event._isModified = true;
    }
}

// Store the original addEventListener method
const originalAddEventListener = EventTarget.prototype.addEventListener;

// Override the addEventListener method
EventTarget.prototype.addEventListener = function(type, listener, options) {
    if (type === 'click') {
        const wrappedListener = function(event) {
            // Modify the click event properties
            modifyClickEvent(event);

            // Call the original listener with the modified event
            listener.call(this, event);
        };
        // Call the original addEventListener with the wrapped listener
        originalAddEventListener.call(this, type, wrappedListener, options);
    } else {
        // Call the original addEventListener for other event types
        originalAddEventListener.call(this, type, listener, options);
    }
};

Use page.add_init_js() to inject this script into the page before calling page.get() I think CF also listens to mousedown and mouseup so you'll need to hook those too. I haven't tested the above method yet because turnstile never blocked me for simulated click(). I was not using headless mode and had fake display size set to 1680x1050

it works, thank you!

viponedream commented 1 month ago

click() 方法无法触发成功,而手动点击可以成功的原因是,click() 方法触发的事件中,ClientX, ClientY和ScreenX, ScreenY 属性相同,而手动点击触发的事件不同。

大佬,你是如果处理的

这个是我的解决方案,获取坐标,使用pyautogui点击。注意在图形界面上PageX,和PageY的获取可能有问题,要加上--start-fullscreen启动参数。NO GUI的话加上--start-maximized启动参数

            wrapper = self.page.ele(".cf-turnstile-wrapper")
            shadow_root = wrapper.shadow_root
            iframe = shadow_root.ele("tag=iframe", timeout=15)
            verify_element = iframe.ele("Verify you are human", timeout=25)
            time.sleep(random.uniform(2, 5))

            # 2024-07-05
            # 直接在element上执行click(通过CDP协议)无法通过cloudflare challenge
            # 原因:
            # CDP命令执行的event中client_x, client_y与screen_x, screen_y是一样的,而手动点击触发的事件两者是不一样的,所以无法使用CDP模拟出鼠标点击通过验证
            # 解决方法:
            # 先获取点击的坐标,使用pyautogui模拟鼠标点击
            # CDP参考 https://chromedevtools.github.io/devtools-protocol/tot/Input/
            # verify_element.click()
            def generate_biased_random(n):
                weights = [min(i, n - i + 1) for i in range(1, n + 1)]
                return random.choices(range(1, n + 1), weights=weights)[0]

            screen_x, screen_y = verify_element.rect.screen_location
            page_x, page_y = self.page.rect.page_location
            width, height = verify_element.rect.size
            offset_x, offset_y = generate_biased_random(
                int(width - 1)
            ), generate_biased_random(int(height - 1))

            click_x, click_y = (
                screen_x + page_x + offset_x,
                screen_y + page_y + offset_y,
            )

            logger.info(
                f"[CloudflareBypass.try_to_click_challenge] Screen point [{screen_x}, {screen_y}]"
            )
            logger.info(
                f"[CloudflareBypass.try_to_click_challenge] Page point[{page_x}, {page_y}]"
            )
            logger.info(
                f"[CloudflareBypass.try_to_click_challenge] Click point [{click_x}, {click_y}]"
            )
            pyautogui.moveTo(
                click_x, click_y, duration=0.5, tween=pyautogui.easeInElastic
            )
            pyautogui.click()
            self.page.wait.load_start(timeout=20)

可以了感谢大佬

我这个脚本,它取出来的坐标不对, move to 位置不对。 大家是怎么取到正确的坐标的呢

riruigit commented 1 month ago

click() 方法无法触发成功,而手动点击可以成功的原因是,click() 方法触发的事件中,ClientX, ClientY和ScreenX, ScreenY 属性相同,而手动点击触发的事件不同。

大佬,你是如果处理的

这个是我的解决方案,获取坐标,使用pyautogui点击。注意在图形界面上PageX,和PageY的获取可能有问题,要加上--start-fullscreen启动参数。NO GUI的话加上--start-maximized启动参数

            wrapper = self.page.ele(".cf-turnstile-wrapper")
            shadow_root = wrapper.shadow_root
            iframe = shadow_root.ele("tag=iframe", timeout=15)
            verify_element = iframe.ele("Verify you are human", timeout=25)
            time.sleep(random.uniform(2, 5))

            # 2024-07-05
            # 直接在element上执行click(通过CDP协议)无法通过cloudflare challenge
            # 原因:
            # CDP命令执行的event中client_x, client_y与screen_x, screen_y是一样的,而手动点击触发的事件两者是不一样的,所以无法使用CDP模拟出鼠标点击通过验证
            # 解决方法:
            # 先获取点击的坐标,使用pyautogui模拟鼠标点击
            # CDP参考 https://chromedevtools.github.io/devtools-protocol/tot/Input/
            # verify_element.click()
            def generate_biased_random(n):
                weights = [min(i, n - i + 1) for i in range(1, n + 1)]
                return random.choices(range(1, n + 1), weights=weights)[0]

            screen_x, screen_y = verify_element.rect.screen_location
            page_x, page_y = self.page.rect.page_location
            width, height = verify_element.rect.size
            offset_x, offset_y = generate_biased_random(
                int(width - 1)
            ), generate_biased_random(int(height - 1))

            click_x, click_y = (
                screen_x + page_x + offset_x,
                screen_y + page_y + offset_y,
            )

            logger.info(
                f"[CloudflareBypass.try_to_click_challenge] Screen point [{screen_x}, {screen_y}]"
            )
            logger.info(
                f"[CloudflareBypass.try_to_click_challenge] Page point[{page_x}, {page_y}]"
            )
            logger.info(
                f"[CloudflareBypass.try_to_click_challenge] Click point [{click_x}, {click_y}]"
            )
            pyautogui.moveTo(
                click_x, click_y, duration=0.5, tween=pyautogui.easeInElastic
            )
            pyautogui.click()
            self.page.wait.load_start(timeout=20)

可以了感谢大佬

我这个脚本,它取出来的坐标不对, move to 位置不对。 大家是怎么取到正确的坐标的呢

是不是分辨率的问题,页面存在拉伸

fancy45daddy commented 4 days ago

@g1879 能解释一下 tab.move_to和pyautogui.moveTo 的区别吗