CloudflareBypasser.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import time
  2. from DrissionPage import ChromiumPage
  3. from loguru import logger
  4. class CloudflareBypasser:
  5. """
  6. 用于绕过 Cloudflare 页面
  7. :param driver: ChromiumPage 对象
  8. :param max_retries: 最大重试次数,默认为 -1
  9. :param log: 日志记录器,默认为 None
  10. """
  11. def __init__(self, driver: ChromiumPage, max_retries=-1, log=None):
  12. self.driver = driver
  13. self.max_retries = max_retries
  14. # self.log = log
  15. self.log = log or logger
  16. def search_recursively_shadow_root_with_iframe(self,ele):
  17. if ele.shadow_root:
  18. if ele.shadow_root.child().tag == "iframe":
  19. return ele.shadow_root.child()
  20. else:
  21. for child in ele.children():
  22. result = self.search_recursively_shadow_root_with_iframe(child)
  23. if result:
  24. return result
  25. return None
  26. def search_recursively_shadow_root_with_cf_input(self,ele):
  27. if ele.shadow_root:
  28. if ele.shadow_root.ele("tag:input"):
  29. return ele.shadow_root.ele("tag:input")
  30. else:
  31. for child in ele.children():
  32. result = self.search_recursively_shadow_root_with_cf_input(child)
  33. if result:
  34. return result
  35. return None
  36. def locate_cf_button(self):
  37. button = None
  38. eles = self.driver.eles("tag:input")
  39. for ele in eles:
  40. if "name" in ele.attrs.keys() and "type" in ele.attrs.keys():
  41. if "turnstile" in ele.attrs["name"] and ele.attrs["type"] == "hidden":
  42. button = ele.parent().shadow_root.child()("tag:body").shadow_root("tag:input")
  43. break
  44. if button:
  45. return button
  46. else:
  47. # If the button is not found, search it recursively
  48. self.log_message("Basic search failed. Searching for button recursively.")
  49. ele = self.driver.ele("tag:body")
  50. iframe = self.search_recursively_shadow_root_with_iframe(ele)
  51. if iframe:
  52. button = self.search_recursively_shadow_root_with_cf_input(iframe("tag:body"))
  53. else:
  54. self.log_message("Iframe not found. Button search failed.")
  55. return button
  56. def log_message(self, message):
  57. if self.log:
  58. # print(message)
  59. self.log.info(message)
  60. def click_verification_button(self):
  61. try:
  62. button = self.locate_cf_button()
  63. if button:
  64. self.log_message("Verification button found. Attempting to click.")
  65. button.click()
  66. else:
  67. self.log_message("Verification button not found.")
  68. except Exception as e:
  69. self.log_message(f"Error clicking verification button: {e}")
  70. def is_bypassed(self):
  71. try:
  72. title = self.driver.title.lower()
  73. return "just a moment" not in title
  74. except Exception as e:
  75. self.log_message(f"Error checking page title: {e}")
  76. return False
  77. def bypass(self):
  78. try_count = 0
  79. while not self.is_bypassed():
  80. if 0 < self.max_retries + 1 <= try_count:
  81. self.log_message("Exceeded maximum retries. Bypass failed.")
  82. break
  83. self.log_message(f"Attempt {try_count + 1}: Verification page detected. Trying to bypass...")
  84. self.click_verification_button()
  85. try_count += 1
  86. time.sleep(2)
  87. if self.is_bypassed():
  88. self.log_message("Bypass successful.")
  89. else:
  90. self.log_message("Bypass failed.")