base_page.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import time
  2. from selenium.webdriver.support.ui import WebDriverWait
  3. from selenium.webdriver.support import expected_conditions as EC
  4. from selenium.webdriver.common.keys import Keys
  5. from selenium.webdriver.support.ui import WebDriverWait
  6. from selenium.webdriver.support import expected_conditions as EC
  7. from selenium.webdriver.common.keys import Keys
  8. class BasePage:
  9. def __init__(self, driver):
  10. self.driver = driver
  11. self.wait = WebDriverWait(driver, 20) # 增加默认等待时间
  12. self.short_wait = WebDriverWait(driver, 5) # 添加短等待
  13. self.long_wait = WebDriverWait(driver, 30) # 添加长等待
  14. def find_element(self, by, locator, timeout=None, check_visibility=True):
  15. """等待并查找单个元素"""
  16. wait = WebDriverWait(self.driver, timeout) if timeout else self.wait
  17. try:
  18. if check_visibility:
  19. return wait.until(EC.visibility_of_element_located((by, locator)))
  20. else:
  21. return wait.until(EC.presence_of_element_located((by, locator)))
  22. except:
  23. # 如果找不到元素,打印页面状态
  24. print("页面状态:", self.get_page_state())
  25. raise
  26. def find_element_directly(self, by, locator):
  27. """直接查找元素,不等待"""
  28. return self.driver.find_element(by, locator)
  29. def find_clickable_element(self, by, locator, timeout=None):
  30. """等待并查找可点击元素"""
  31. wait = WebDriverWait(self.driver, timeout) if timeout else self.wait
  32. try:
  33. return wait.until(EC.element_to_be_clickable((by, locator)))
  34. except:
  35. # 如果找不到元素,打印页面状态
  36. print("页面状态:", self.get_page_state())
  37. raise
  38. def get_page_state(self):
  39. """获取页面状态信息"""
  40. try:
  41. return {
  42. 'url': self.driver.current_url,
  43. 'ready_state': self.driver.execute_script('return document.readyState'),
  44. 'is_iframe': len(self.driver.find_elements(by='tag name', value='iframe')) > 0,
  45. 'page_source_length': len(self.driver.page_source)
  46. }
  47. except Exception as e:
  48. return f"获取页面状态失败: {str(e)}"
  49. def safe_click(self, element):
  50. """安全点击元素,如果普通点击失败则使用JS点击"""
  51. try:
  52. self.driver.execute_script("arguments[0].scrollIntoView(true);", element)
  53. time.sleep(1)
  54. element.click()
  55. except Exception as e:
  56. print(f"常规点击失败,尝试JS点击: {str(e)}")
  57. self.driver.execute_script("arguments[0].click();", element)
  58. def safe_send_keys(self, element, text):
  59. """
  60. 安全输入文本,支持emoji
  61. 使用分段输入的方式,确保emoji字符能够正确输入
  62. """
  63. try:
  64. element.clear()
  65. # 先点击确保焦点
  66. element.click()
  67. time.sleep(0.5)
  68. # 使用clipboard.js来处理复制粘贴
  69. self.driver.execute_script("""
  70. if (!window.clipboardJS) {
  71. window.clipboardJS = true;
  72. var script = document.createElement('script');
  73. script.src = 'https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.8/clipboard.min.js';
  74. document.head.appendChild(script);
  75. }
  76. """)
  77. time.sleep(1) # 等待脚本加载
  78. # 创建临时输入区域并复制文本
  79. self.driver.execute_script("""
  80. // 创建临时textarea
  81. var textarea = document.createElement('textarea');
  82. textarea.value = arguments[0];
  83. textarea.style.position = 'fixed';
  84. textarea.style.opacity = '0';
  85. document.body.appendChild(textarea);
  86. // 选择文本
  87. textarea.select();
  88. // 复制
  89. document.execCommand('copy');
  90. // 清理
  91. document.body.removeChild(textarea);
  92. """, text)
  93. # 模拟粘贴操作
  94. element.send_keys(Keys.CONTROL + 'v') # Windows
  95. time.sleep(0.5)
  96. except Exception as e:
  97. print(f"复杂输入方式失败,尝试直接输入: {str(e)}")
  98. try:
  99. # 如果复杂方式失败,回退到直接输入
  100. element.clear()
  101. element.send_keys(text)
  102. except Exception as e2:
  103. print(f"所有输入方式都失败: {str(e2)}")
  104. raise
  105. def __init__(self, driver):
  106. self.driver = driver
  107. self.wait = WebDriverWait(driver, 10)
  108. def find_element(self, by, locator):
  109. """等待并查找单个元素"""
  110. return self.wait.until(EC.presence_of_element_located((by, locator)))
  111. def find_element_directly(self, by, locator):
  112. """等待并查找多个元素"""
  113. return self.driver.find_element(by, locator)
  114. def find_clickable_element(self, by, locator):
  115. """等待并查找可点击元素"""
  116. return self.wait.until(EC.element_to_be_clickable((by, locator)))
  117. def safe_click(self, element):
  118. """安全点击元素,如果普通点击失败则使用JS点击"""
  119. try:
  120. self.driver.execute_script("arguments[0].scrollIntoView(true);", element)
  121. time.sleep(1)
  122. element.click()
  123. except Exception as e:
  124. print(f"常规点击失败,尝试JS点击: {str(e)}")
  125. self.driver.execute_script("arguments[0].click();", element)
  126. def safe_send_keys(self, element, text):
  127. """
  128. 安全输入文本,支持emoji
  129. 使用分段输入的方式,确保emoji字符能够正确输入
  130. """
  131. try:
  132. element.clear()
  133. # 先点击确保焦点
  134. element.click()
  135. time.sleep(0.5)
  136. # 使用clipboard.js来处理复制粘贴
  137. self.driver.execute_script("""
  138. if (!window.clipboardJS) {
  139. window.clipboardJS = true;
  140. var script = document.createElement('script');
  141. script.src = 'https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.8/clipboard.min.js';
  142. document.head.appendChild(script);
  143. }
  144. """)
  145. time.sleep(1) # 等待脚本加载
  146. # 创建临时输入区域并复制文本
  147. self.driver.execute_script("""
  148. // 创建临时textarea
  149. var textarea = document.createElement('textarea');
  150. textarea.value = arguments[0];
  151. textarea.style.position = 'fixed';
  152. textarea.style.opacity = '0';
  153. document.body.appendChild(textarea);
  154. // 选择文本
  155. textarea.select();
  156. // 复制
  157. document.execCommand('copy');
  158. // 清理
  159. document.body.removeChild(textarea);
  160. """, text)
  161. # 模拟粘贴操作
  162. element.send_keys(Keys.CONTROL + 'v') # Windows
  163. time.sleep(0.5)
  164. except Exception as e:
  165. print(f"复杂输入方式失败,尝试直接输入: {str(e)}")
  166. try:
  167. # 如果复杂方式失败,回退到直接输入
  168. element.clear()
  169. element.send_keys(text)
  170. except Exception as e2:
  171. print(f"所有输入方式都失败: {str(e2)}")
  172. raise