40a24e98e5badf8809cb281ca9189947.txt 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. from appium import webdriver
  2. from appium.options.android import UiAutomator2Options
  3. from appium.webdriver.common.appiumby import AppiumBy
  4. from selenium.webdriver.support.ui import WebDriverWait
  5. from selenium.webdriver.support import expected_conditions as EC
  6. from selenium.common.exceptions import TimeoutException
  7. import time
  8. import logging
  9. import subprocess
  10. import os
  11. # 配置日志
  12. logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
  13. logger = logging.getLogger(__name__)
  14. # Desired capabilities
  15. desired_caps = {
  16. "platformName": "Android",
  17. "platformVersion": "12",
  18. "deviceName": "emulator-5558",
  19. "appPackage": "com.phoenix.read",
  20. "appActivity": "com.dragon.read.pages.splash.SplashActivity",
  21. "automationName": "UiAutomator2",
  22. "noReset": True,
  23. "fullReset": False,
  24. "autoGrantPermissions": True,
  25. "appium:ensureWebviewsHavePages": False,
  26. "appium:uiautomator2ServerLaunchTimeout": 120000,
  27. "appium:uiautomator2ServerInstallTimeout": 120000,
  28. "appium:newCommandTimeout": 14400,
  29. "appium:adbExecTimeout": 60000
  30. }
  31. # 初始化 driver
  32. driver = None
  33. options = UiAutomator2Options().load_capabilities(desired_caps)
  34. try:
  35. driver = webdriver.Remote('http://localhost:4723/wd/hub', options=options)
  36. logger.info("Appium 连接成功")
  37. except Exception as e:
  38. logger.error(f"连接失败: {str(e)}")
  39. exit(1)
  40. def check_app_alive(max_attempts=3):
  41. """检查应用是否存活,若闪退则尝试重启"""
  42. logger.info("检查应用状态")
  43. global driver
  44. if driver is None:
  45. logger.error("driver 未初始化")
  46. return False
  47. for attempt in range(max_attempts):
  48. try:
  49. current_activity = driver.current_activity
  50. if current_activity and (
  51. "com.phoenix.read" in current_activity or
  52. "com.dragon.read" in current_activity or
  53. "com.ss.android.excitingvideo" in current_activity
  54. ):
  55. logger.info(f"应用存活,当前 Activity: {current_activity}")
  56. return True
  57. else:
  58. logger.error(f"检测到非应用/广告 Activity: {current_activity}")
  59. raise Exception("非应用 Activity")
  60. except Exception as e:
  61. logger.error(f"应用可能闪退,尝试重启(第 {attempt + 1}/{max_attempts} 次): {str(e)}")
  62. try:
  63. # 停止广告和应用进程
  64. subprocess.run(["adb", "shell", "am", "force-stop", "com.ss.android.excitingvideo"], check=True)
  65. subprocess.run(["adb", "shell", "am", "force-stop", "com.phoenix.read"], check=True)
  66. time.sleep(2)
  67. try:
  68. with open(f"crash_page_source_attempt_{attempt + 1}.xml", "w", encoding="utf-8") as f:
  69. f.write(driver.page_source)
  70. except:
  71. logger.warning("无法保存崩溃页面源")
  72. try:
  73. driver.start_activity("com.phoenix.read", "com.dragon.read.pages.splash.SplashActivity")
  74. except AttributeError:
  75. subprocess.run(["adb", "shell", "am", "start", "-n",
  76. "com.phoenix.read/com.dragon.read.pages.splash.SplashActivity"], check=True)
  77. time.sleep(8)
  78. logger.info("应用重启成功")
  79. try:
  80. handle_popup(fast=False)
  81. if find_and_click_element(
  82. (AppiumBy.ID, "com.phoenix.read:id/adx"),
  83. "首页按钮",
  84. wait_time=10
  85. ):
  86. logger.info("重启后已点击首页")
  87. time.sleep(1)
  88. handle_popup(fast=True)
  89. return True
  90. else:
  91. raise Exception("点击首页按钮失败")
  92. except Exception as ex:
  93. logger.error(f"重启后进入首页失败: {str(ex)}")
  94. with open(f"home_error_page_source_attempt_{attempt + 1}.xml", "w", encoding="utf-8") as f:
  95. f.write(driver.page_source)
  96. except Exception as ex:
  97. logger.error(f"应用重启失败: {str(ex)}")
  98. if attempt < max_attempts - 1:
  99. logger.info("尝试重启 Appium 会话")
  100. try:
  101. driver.quit()
  102. except:
  103. pass
  104. time.sleep(5)
  105. try:
  106. driver = webdriver.Remote('http://localhost:4723/wd/hub', options=options)
  107. logger.info("Appium 会话重启成功")
  108. time.sleep(5)
  109. except Exception as re:
  110. logger.error(f"Appium 会话重启失败: {str(re)}")
  111. driver = None
  112. time.sleep(1)
  113. logger.error("应用多次重启失败")
  114. return False
  115. def handle_popup(fast=False):
  116. """处理弹窗,增强登录处理"""
  117. logger.info("处理弹窗")
  118. if driver is None:
  119. logger.error("driver 未初始化")
  120. return
  121. wait_time = 2 if fast else 5
  122. popups = [
  123. '//android.widget.Button[contains(@text, "确定") or contains(@text, "关闭") or contains(@text, "取消") or contains(@text, "允许") or contains(@text, "拒绝") or contains(@text, "登录") or contains(@text, "立即登录") or contains(@content-desc, "登录")]',
  124. '//android.widget.ImageView[@content-desc="关闭" or contains(@content-desc, "close") or contains(@content-desc, "关闭广告")]',
  125. '//android.view.View[@content-desc="关闭" or contains(@content-desc, "close") or contains(@content-desc, "关闭广告")]',
  126. '//android.widget.FrameLayout[contains(@content-desc, "关闭") or contains(@content-desc, "close") or contains(@content-desc, "关闭广告")]',
  127. '//android.widget.TextView[contains(@text, "关闭") or contains(@text, "取消")]', # 新增:处理可能的 TextView 关闭按钮
  128. ]
  129. for xpath in popups:
  130. try:
  131. popup_button = WebDriverWait(driver, timeout=wait_time).until(
  132. EC.element_to_be_clickable((AppiumBy.XPATH, xpath))
  133. )
  134. popup_button.click()
  135. logger.info(f"处理了弹窗: {xpath}")
  136. time.sleep(0.5 if fast else 1)
  137. except TimeoutException:
  138. logger.debug(f"未检测到弹窗: {xpath}")
  139. except Exception as e:
  140. logger.error(f"弹窗处理失败: {str(e)}")
  141. def find_and_click_element(locator, description, wait_time=10):
  142. """检查元素存在并点击"""
  143. logger.info(f"尝试点击: {description}")
  144. try:
  145. elements = WebDriverWait(driver, wait_time).until(
  146. EC.presence_of_all_elements_located(locator)
  147. )
  148. if elements:
  149. elements[0].click()
  150. logger.info(f"成功点击: {description}")
  151. return True
  152. else:
  153. logger.error(f"未找到: {description}")
  154. with open(f"find_error_{description}.xml", "w", encoding="utf-8") as f:
  155. f.write(driver.page_source)
  156. try:
  157. driver.get_screenshot_as_file(f"find_error_{description}.png")
  158. logger.info(f"已保存截图: find_error_{description}.png")
  159. except Exception as e:
  160. logger.error(f"保存截图失败: {str(e)}")
  161. return False
  162. except TimeoutException as e:
  163. logger.error(f"查找超时: {description}, 错误: {str(e)}")
  164. with open(f"find_error_{description}.xml", "w", encoding="utf-8") as f:
  165. f.write(driver.page_source)
  166. try:
  167. driver.get_screenshot_as_file(f"find_error_{description}.png")
  168. logger.info(f"已保存截图: find_error_{description}.png")
  169. except Exception as e:
  170. logger.error(f"保存截图失败: {str(e)}")
  171. return False
  172. except Exception as e:
  173. logger.error(f"点击失败: {description}, 错误: {str(e)}")
  174. with open(f"find_error_{description}.xml", "w", encoding="utf-8") as f:
  175. f.write(driver.page_source)
  176. try:
  177. driver.get_screenshot_as_file(f"find_error_{description}.png")
  178. logger.info(f"已保存截图: find_error_{description}.png")
  179. except Exception as e:
  180. logger.error(f"保存截图失败: {str(e)}")
  181. return False
  182. def click_welfare_button():
  183. """点击福利按钮"""
  184. logger.info("点击福利按钮")
  185. handle_popup(fast=True)
  186. if not find_and_click_element(
  187. (AppiumBy.ID, "com.phoenix.read:id/adw"),
  188. "福利按钮",
  189. wait_time=8
  190. ):
  191. with open("adw_error.xml", "w", encoding="utf-8") as f:
  192. f.write(driver.page_source)
  193. raise Exception("点击福利按钮失败")
  194. time.sleep(1)
  195. def handle_sign_in():
  196. """处理签到,仅首次"""
  197. logger.info("处理签到")
  198. handle_popup(fast=False) # 慢速清理弹窗,确保页面干净
  199. # 定义“去签到”按钮的定位器
  200. go_sign_in_locators = [
  201. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.LynxFlattenUI[@content-desc="去签到"]'),
  202. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.LynxFlattenUI[@index="353"]'),
  203. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.LynxFlattenUI[@index="354"]'),
  204. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.LynxFlattenUI[contains(@text, "去签到")]'),
  205. (AppiumBy.XPATH,
  206. '/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout[1]/android.widget.FrameLayout[2]/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/com.lynx.tasm.behavior.ui.LynxFlattenUI[81]'),
  207. ]
  208. # 定义“立即签到”按钮的定位器
  209. sign_in_locators = [
  210. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.view.UIView[@content-desc="立即签到"]'),
  211. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.view.UIView[contains(@content-desc, "立即签到")]'),
  212. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.view.UIView[@index="317"]'),
  213. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.view.UIView[contains(@text, "立即签到")]'),
  214. ]
  215. def try_click_button(locators, description, wait_time=8):
  216. """尝试点击按钮,支持多重定位和点击方式"""
  217. for locator in locators:
  218. try:
  219. # 检查元素是否存在
  220. elements = driver.find_elements(*locator)
  221. if not elements:
  222. logger.debug(f"未找到‘{description}’元素(locator: {locator[1]})")
  223. continue
  224. button = WebDriverWait(driver, timeout=wait_time).until(
  225. EC.element_to_be_clickable(locator)
  226. )
  227. # 获取按钮属性
  228. attributes = {
  229. "clickable": button.get_attribute("clickable") or "N/A",
  230. "enabled": button.get_attribute("enabled") or "N/A",
  231. "bounds": button.get_attribute("bounds") or "N/A",
  232. "displayed": button.get_attribute("displayed") or "N/A",
  233. "content-desc": button.get_attribute("content-desc") or "N/A",
  234. "text": button.get_attribute("text") or "N/A",
  235. }
  236. logger.info(f"{description}按钮属性: {attributes}")
  237. # 尝试标准点击
  238. button.click()
  239. logger.info(f"已点击‘{description}’(locator={locator[1]})")
  240. return True
  241. except TimeoutException:
  242. logger.error(f"未找到或无法点击‘{description}’(locator: {locator[1]})")
  243. # 尝试 JavaScript 点击
  244. try:
  245. elements = driver.find_elements(*locator)
  246. if elements:
  247. driver.execute_script("arguments[0].click();", elements[0])
  248. logger.info(f"通过 JavaScript 点击‘{description}’成功(locator: {locator[1]})")
  249. return True
  250. except Exception as e:
  251. logger.error(f"JavaScript 点击‘{description}’失败(locator: {locator[1]}): {str(e)}")
  252. # 尝试坐标点击
  253. try:
  254. elements = driver.find_elements(*locator)
  255. if elements:
  256. bounds = elements[0].get_attribute("bounds")
  257. import re
  258. coords = re.match(r"\[(\d+),(\d+)\]\[(\d+),(\d+)\]", bounds)
  259. if coords:
  260. x = (int(coords.group(1)) + int(coords.group(3))) // 2
  261. y = (int(coords.group(2)) + int(coords.group(4))) // 2
  262. driver.tap([(x, y)])
  263. logger.info(f"通过坐标点击 (x={x}, y={y}) 成功(locator: {locator[1]})")
  264. return True
  265. else:
  266. logger.error(f"无法解析 bounds 属性(locator: {locator[1]})")
  267. except Exception as e:
  268. logger.error(f"坐标点击‘{description}’失败(locator: {locator[1]}): {str(e)}")
  269. # 保存调试信息
  270. with open(f"click_error_{description}.xml", "w", encoding="utf-8") as f:
  271. f.write(driver.page_source)
  272. try:
  273. driver.get_screenshot_as_file(f"click_error_{description}.png")
  274. logger.info(f"已保存截图: click_error_{description}.png")
  275. except Exception as e:
  276. logger.error(f"保存截图失败: {str(e)}")
  277. return False
  278. # 刷新页面
  279. logger.info("尝试刷新页面状态")
  280. try:
  281. find_and_click_element(
  282. (AppiumBy.ID, "com.phoenix.read:id/adx"),
  283. "首页按钮",
  284. wait_time=8
  285. )
  286. time.sleep(2)
  287. click_welfare_button()
  288. handle_popup(fast=False)
  289. except Exception as e:
  290. logger.warning(f"页面刷新失败: {str(e)}")
  291. # 尝试点击“去签到”
  292. logger.info("尝试点击‘去签到’")
  293. if try_click_button(go_sign_in_locators, "去签到", wait_time=8):
  294. logger.info("已点击‘去签到’,检查‘立即签到’")
  295. time.sleep(2) # 等待弹窗出现
  296. handle_popup(fast=True)
  297. # 点击“去签到”后检查“立即签到”
  298. if try_click_button(sign_in_locators, "立即签到", wait_time=8):
  299. logger.info("已点击‘立即签到’,签到完成")
  300. else:
  301. with open("claim_error_sign_after_go.xml", "w", encoding="utf-8") as f:
  302. f.write(driver.page_source)
  303. try:
  304. driver.get_screenshot_as_file("claim_error_sign_after_go.png")
  305. logger.info("已保存截图: claim_error_sign_after_go.png")
  306. except Exception as e:
  307. logger.error(f"保存截图失败: {str(e)}")
  308. logger.error("点击‘去签到’后仍未找到或无法点击‘立即签到’")
  309. raise Exception("点击‘立即签到’失败")
  310. else:
  311. with open("claim_error_sign_no_go.xml", "w", encoding="utf-8") as f:
  312. f.write(driver.page_source)
  313. try:
  314. driver.get_screenshot_as_file("claim_error_sign_no_go.png")
  315. logger.info("已保存截图: claim_error_sign_no_go.png")
  316. except Exception as e:
  317. logger.error(f"保存截图失败: {str(e)}")
  318. logger.error("未找到‘去签到’")
  319. raise Exception("签到流程失败")
  320. def go_to_home_and_play_video():
  321. """去首页并刷视频"""
  322. logger.info("进入首页并刷视频")
  323. handle_popup(fast=True)
  324. start_time = time.time()
  325. if not find_and_click_element(
  326. (AppiumBy.ID, "com.phoenix.read:id/adx"),
  327. "首页按钮",
  328. wait_time=8
  329. ):
  330. with open("home_error.xml", "w", encoding="utf-8") as f:
  331. f.write(driver.page_source)
  332. try:
  333. driver.get_screenshot_as_file("home_error.png")
  334. logger.info("已保存截图: home_error.png")
  335. except Exception as e:
  336. logger.error(f"保存截图失败: {str(e)}")
  337. raise Exception("点击首页按钮失败")
  338. time.sleep(1)
  339. logger.info(f"当前 Activity: {driver.current_activity}")
  340. logger.info("在首页停留22秒...")
  341. time.sleep(22)
  342. handle_popup(fast=True)
  343. current_activity_before = driver.current_activity
  344. logger.info(f"福利按钮前 Activity: {current_activity_before}")
  345. if not find_and_click_element(
  346. (AppiumBy.ID, "com.phoenix.read:id/adw"),
  347. "再次点击福利",
  348. wait_time=8
  349. ):
  350. with open("adw2_error.xml", "w", encoding="utf-8") as f:
  351. f.write(driver.page_source)
  352. try:
  353. driver.get_screenshot_as_file("adw2_error.png")
  354. logger.info("已保存截图: adw2_error.png")
  355. except Exception as e:
  356. logger.error(f"保存截图失败: {str(e)}")
  357. logger.error("再次点击福利失败")
  358. raise Exception("点击福利按钮失败")
  359. handle_popup(fast=True)
  360. # 定义“立即领取”按钮的定位器
  361. claim_locators = [
  362. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.LynxFlattenUI[@content-desc="立即领取"]'),
  363. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.LynxFlattenUI[contains(@content-desc, "立即领取")]'),
  364. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.LynxFlattenUI[contains(@text, "立即领取")]'),
  365. ]
  366. # 定义“领取成功”按钮的定位器
  367. success_locators = [
  368. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.LynxFlattenUI[@content-desc="领取成功"]'),
  369. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.LynxFlattenUI[contains(@content-desc, "领取成功")]'),
  370. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.LynxFlattenUI[@index="18"]'),
  371. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.LynxFlattenUI[contains(@text, "领取成功")]'),
  372. ]
  373. if try_click_button(claim_locators, "立即领取", wait_time=10):
  374. logger.info("已点击‘立即领取’,等待视频播放45秒")
  375. time.sleep(45) # 等待视频播放
  376. handle_popup(fast=True)
  377. # 检查并点击“领取成功”按钮
  378. if try_click_button(success_locators, "领取成功", wait_time=8):
  379. logger.info("已点击‘领取成功’,视频奖励领取完成")
  380. else:
  381. with open("claim_success_error.xml", "w", encoding="utf-8") as f:
  382. f.write(driver.page_source)
  383. try:
  384. driver.get_screenshot_as_file("claim_success_error.png")
  385. logger.info("已保存截图: claim_success_error.png")
  386. except Exception as e:
  387. logger.error(f"保存截图失败: {str(e)}")
  388. logger.warning("未找到或无法点击‘领取成功’按钮,视频可能未成功播放")
  389. # 检查应用状态
  390. for _ in range(6): # 检查6次,每次5秒
  391. if check_app_alive():
  392. logger.info("视频播放后应用正常")
  393. return True
  394. time.sleep(5)
  395. logger.error("视频后多次检查闪退")
  396. return False
  397. else:
  398. with open("claim_video_error.xml", "w", encoding="utf-8") as f:
  399. f.write(driver.page_source)
  400. try:
  401. driver.get_screenshot_as_file("claim_video_error.png")
  402. logger.info("已保存截图: claim_video_error.png")
  403. except Exception as e:
  404. logger.error(f"保存截图失败: {str(e)}")
  405. logger.error("点击‘立即领取’失败")
  406. raise Exception("点击‘立即领取’失败")
  407. logger.info(f"加载耗时: {time.time() - start_time:.2f}秒")
  408. return True
  409. def switch_to_welfare_page():
  410. """切换福利页面"""
  411. logger.info("切换到福利页面")
  412. handle_popup(fast=True)
  413. current_activity_before = driver.current_activity
  414. logger.info(f"切换福利前: {current_activity_before}")
  415. if find_and_click_element(
  416. (AppiumBy.ID, "com.phoenix.read:id/adw"),
  417. "切换福利",
  418. wait_time=8
  419. ):
  420. time.sleep(1)
  421. logger.info(f"切换后: {driver.current_activity}")
  422. else:
  423. with open("adw3_error.xml", "w", encoding="utf-8") as f:
  424. f.write(driver.page_source)
  425. try:
  426. driver.get_screenshot_as_file("adw3_error.png")
  427. logger.info("已保存截图: adw3_error.png")
  428. except Exception as e:
  429. logger.error(f"保存截图失败: {str(e)}")
  430. logger.error("切换失败")
  431. raise Exception("切换福利页面失败")
  432. def claim_treasure():
  433. """领取宝箱"""
  434. logger.info("领取宝箱")
  435. handle_popup(fast=True)
  436. if find_and_click_element(
  437. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.view.UIView[@content-desc="开宝箱得金币"]'),
  438. "开宝箱",
  439. wait_time=8
  440. ):
  441. logger.info("已打开宝箱")
  442. time.sleep(1)
  443. else:
  444. with open("treasure_error.xml", "w", encoding="utf-8") as f:
  445. f.write(driver.page_source)
  446. try:
  447. driver.get_screenshot_as_file("treasure_error.png")
  448. logger.info("已保存截图: treasure_error.png")
  449. except Exception as e:
  450. logger.error(f"保存截图失败: {str(e)}")
  451. logger.error("打开宝箱失败")
  452. handle_popup()
  453. if find_and_click_element(
  454. (AppiumBy.XPATH, '//com.lynx.tasm.behavior.ui.LynxFlattenUI[contains(@content-desc, "看视频最高再领")]'),
  455. "看视频",
  456. wait_time=10
  457. ):
  458. logger.info("已点击‘看视频’")
  459. time.sleep(30) # 初始等待
  460. for _ in range(6): # 检查6次,每次5秒
  461. if check_app_alive():
  462. logger.info("视频播放正常")
  463. # 等待关闭按钮
  464. try:
  465. close_ad_button = WebDriverWait(driver, 10).until(
  466. EC.element_to_be_clickable(
  467. (AppiumBy.XPATH,
  468. '//android.widget.ImageView[@content-desc="关闭" or @text="关闭" or contains(@content-desc, "close") or contains(@text, "button") or contains(@content-desc, "关闭广告")]')
  469. )
  470. )
  471. close_ad_button.click()
  472. logger.info("已关闭广告")
  473. time.sleep(1)
  474. return True
  475. except:
  476. logger.info("未检测到关闭按钮,尝试继续")
  477. time.sleep(5)
  478. logger.error("视频后多次检查闪退")
  479. return False
  480. else:
  481. with open("watch_video_error.xml", "w", encoding="utf-8") as f:
  482. f.write(driver.page_source)
  483. try:
  484. driver.get_screenshot_as_file("watch_video_error.png")
  485. logger.info("已保存截图: watch_video_error.png")
  486. except Exception as e:
  487. logger.error(f"保存截图失败: {str(e)}")
  488. logger.error("点击‘看视频’失败")
  489. return True
  490. try:
  491. logger.info("开始执行脚本")
  492. # 优化模拟器
  493. try:
  494. subprocess.run(["adb", "shell", "wm", "size", "720x1280"], check=True)
  495. subprocess.run(["adb", "shell", "wm", "density", "240"], check=True)
  496. logger.info("已设置分辨率720x1280,密度240")
  497. except Exception as e:
  498. logger.error(f"设置模拟器失败: {str(e)}")
  499. # 初始加载
  500. logger.info("等待应用加载")
  501. time.sleep(10)
  502. logger.info(f"当前 Activity: {driver.current_activity}")
  503. # 初始弹窗
  504. handle_popup()
  505. # 执行功能
  506. click_welfare_button()
  507. handle_sign_in()
  508. if go_to_home_and_play_video():
  509. switch_to_welfare_page()
  510. claim_treasure()
  511. # 等待5小时
  512. logger.info("开始等待...")
  513. wait_time = 18000
  514. check_interval = 120
  515. start_time = time.time()
  516. while time.time() - start_time < wait_time:
  517. if not check_app_alive():
  518. logger.error("多次重启动失败,退出")
  519. break
  520. handle_popup(fast=True)
  521. time.sleep(check_interval)
  522. logger.info("应用仍在运行")
  523. except Exception as e:
  524. logger.error(f"脚本错误: {str(e)}")
  525. if driver is not None:
  526. with open("error_page_source.xml", "w", encoding="utf-8") as f:
  527. f.write(driver.page_source)
  528. try:
  529. driver.get_screenshot_as_file("error_page_source.png")
  530. logger.info("已保存截图: error_page_source.png")
  531. except Exception as e:
  532. logger.error(f"保存截图失败: {str(e)}")
  533. finally:
  534. logger.info("脚本执行结束,保持 driver 活跃")