#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 咪咕短剧超级会员 flows.cdyylkj.com/miguSM/home 自动化(DrissionPage + TgeBrowser): 1) 新建 TgeBrowser 浏览器 2) 打开页面,输入手机号,点击发送验证码 → 返回成功 3) 接收验证码并填写、提交 """ from __future__ import annotations import time from typing import Any, Optional from DrissionPage import ChromiumOptions, ChromiumPage MIGU_HOME_URL = "https://flows.cdyylkj.com/miguSM/home" def _find_first(page, selectors: list[str], timeout: float = 8): """尝试多个选择器,返回第一个找到的元素。""" for sel in selectors: try: ele = page.ele(sel, timeout=timeout) if ele: return ele except Exception: continue return None def _click_safe(ele) -> None: try: ele.click() except Exception: try: ele.click(by_js=True) except Exception: ele.run_js("this.click()") def input_phone_and_send_code( page: ChromiumPage, phone: str, url: str = MIGU_HOME_URL, wait_after_open: float = 1.0, ) -> dict: """ 步骤一:输入手机号、点击发送验证码。 返回 {"success": True, "message": "输入电话号码成功"} 或抛出异常。 """ page.get(url) time.sleep(wait_after_open) # 手机号输入框(按常见 H5 表单结构) phone_input = _find_first(page, [ 'x://input[@placeholder*="手机"]', 'x://input[@placeholder*="电话"]', 'x://input[@placeholder*="号码"]', 'x://input[@type="tel"]', 'x://input[@type="number"]', "css:input[type='tel']", "css:input[placeholder*='手机']", "css:input[placeholder*='电话']", "css:input.inp-txt", "css:.phone-input input", "css:input.phone", ], timeout=10) if not phone_input: raise RuntimeError("未找到手机号输入框,请根据页面调整选择器") phone_input.input(phone, clear=True) time.sleep(0.3) # 可选:勾选协议(若页面有) agree = _find_first(page, [ "css:input[type='checkbox']", "css:.agree-checkbox", 'x://input[@type="checkbox"]', 'x://i[contains(@class,"checkbox")]', ], timeout=2) if agree: try: _click_safe(agree) time.sleep(0.2) except Exception: pass # 发送验证码按钮 send_btn = _find_first(page, [ 'x://button[contains(text(),"获取验证码")]', 'x://span[contains(text(),"获取验证码")]', 'x://*[contains(text(),"获取验证码")]', 'x://button[contains(text(),"发送验证码")]', 'x://*[contains(text(),"发送验证码")]', "css:button.btn-code", "css:.send-code", "css:.get-code", "css:button[class*='code']", "css:.verify-btn", ], timeout=8) if not send_btn: raise RuntimeError("未找到「获取验证码」按钮,请根据页面调整选择器") _click_safe(send_btn) time.sleep(0.5) return {"success": True, "message": "输入电话号码成功"} def input_code_and_submit( page: ChromiumPage, code: str, ) -> dict: """ 步骤二:填写验证码并提交(若存在提交按钮)。 返回 {"success": True, "message": "验证码已填写"}。 """ code_input = _find_first(page, [ 'x://input[@placeholder*="验证码"]', 'x://input[@placeholder*="短信"]', 'x://input[@placeholder*="验证"]', "css:input[placeholder*='验证码']", "css:input[placeholder*='短信']", "css:input.code-input", "css:input.verify-input", "css:input[type='text']", "css:input.inp-txt", ], timeout=8) if not code_input: raise RuntimeError("未找到验证码输入框") code_input.input(code, clear=True) time.sleep(0.2) # 若有确认/提交按钮则点击 submit_btn = _find_first(page, [ 'x://button[contains(text(),"确认")]', 'x://button[contains(text(),"提交")]', 'x://*[contains(text(),"确认")]', 'x://*[contains(text(),"登录")]', 'x://*[contains(text(),"绑定")]', "css:button.btn-primary", "css:button.btn-buy", "css:.submit-btn", "css:.confirm-btn", "css:img.btn-buy", ], timeout=5) if submit_btn: _click_safe(submit_btn) return {"success": True, "message": "验证码已填写"} def connect_dp_to_tgebrowser(port: int) -> ChromiumPage: """通过调试端口连接 TgeBrowser 已启动的浏览器。""" co = ChromiumOptions().set_local_port(port=port) return ChromiumPage(addr_or_opts=co) def connect_dp_to_ws(ws_url: str) -> ChromiumPage: """通过 WebSocket 地址连接 TgeBrowser。""" return ChromiumPage(addr_or_opts=ws_url)