import time from DrissionPage import ChromiumPage from loguru import logger class CloudflareBypasser: """ 用于绕过 Cloudflare 页面 :param driver: ChromiumPage 对象 :param max_retries: 最大重试次数,默认为 -1 :param log: 日志记录器,默认为 None """ def __init__(self, driver: ChromiumPage, max_retries=-1, log=None): self.driver = driver self.max_retries = max_retries # self.log = log self.log = log or logger def search_recursively_shadow_root_with_iframe(self,ele): if ele.shadow_root: if ele.shadow_root.child().tag == "iframe": return ele.shadow_root.child() else: for child in ele.children(): result = self.search_recursively_shadow_root_with_iframe(child) if result: return result return None def search_recursively_shadow_root_with_cf_input(self,ele): if ele.shadow_root: if ele.shadow_root.ele("tag:input"): return ele.shadow_root.ele("tag:input") else: for child in ele.children(): result = self.search_recursively_shadow_root_with_cf_input(child) if result: return result return None def locate_cf_button(self): button = None eles = self.driver.eles("tag:input") for ele in eles: if "name" in ele.attrs.keys() and "type" in ele.attrs.keys(): if "turnstile" in ele.attrs["name"] and ele.attrs["type"] == "hidden": button = ele.parent().shadow_root.child()("tag:body").shadow_root("tag:input") break if button: return button else: # If the button is not found, search it recursively self.log_message("Basic search failed. Searching for button recursively.") ele = self.driver.ele("tag:body") iframe = self.search_recursively_shadow_root_with_iframe(ele) if iframe: button = self.search_recursively_shadow_root_with_cf_input(iframe("tag:body")) else: self.log_message("Iframe not found. Button search failed.") return button def log_message(self, message): if self.log: # print(message) self.log.info(message) def click_verification_button(self): try: button = self.locate_cf_button() if button: self.log_message("Verification button found. Attempting to click.") button.click() else: self.log_message("Verification button not found.") except Exception as e: self.log_message(f"Error clicking verification button: {e}") def is_bypassed(self): try: title = self.driver.title.lower() return "just a moment" not in title except Exception as e: self.log_message(f"Error checking page title: {e}") return False def bypass(self): try_count = 0 while not self.is_bypassed(): if 0 < self.max_retries + 1 <= try_count: self.log_message("Exceeded maximum retries. Bypass failed.") break self.log_message(f"Attempt {try_count + 1}: Verification page detected. Trying to bypass...") self.click_verification_button() try_count += 1 time.sleep(2) if self.is_bypassed(): self.log_message("Bypass successful.") else: self.log_message("Bypass failed.")