From f799a6df777e9e756defe306c1c349d6f69b5bd2 Mon Sep 17 00:00:00 2001 From: zhangkai <2403741920@qq.com> Date: Thu, 13 Nov 2025 19:31:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=94=AF=E6=8C=81=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E5=88=86=E8=BE=A8=E7=8E=87=E4=B8=BA2.0=E7=9A=84?= =?UTF-8?q?=E6=9C=BA=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Utils/AiUtils.py | 14 ++- Utils/ControlUtils.py | 35 +++++--- Utils/OCRUtils.py | 13 ++- resources/comment2.png | Bin 0 -> 3544 bytes resources/insert_comment2x.png | Bin 0 -> 3630 bytes resources/like1.png | Bin 0 -> 1218 bytes script/ScriptManager.py | 154 +++++++++++++++++++++------------ 7 files changed, 148 insertions(+), 68 deletions(-) create mode 100644 resources/comment2.png create mode 100644 resources/insert_comment2x.png create mode 100644 resources/like1.png diff --git a/Utils/AiUtils.py b/Utils/AiUtils.py index 648387a..8d8444a 100644 --- a/Utils/AiUtils.py +++ b/Utils/AiUtils.py @@ -86,7 +86,7 @@ class AiUtils(object): # 模板匹配 res = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED) - threshold = 0.7 + threshold = 0.85 loc = np.where(res >= threshold) # 放在 cv2.matchTemplate 之前 cv2.imwrite(f'/tmp/runtime_bg_{udid}.png', image) @@ -1394,4 +1394,14 @@ class AiUtils(object): - + @classmethod + def _screen_info(cls, udid: str): + try: + # 避免 c.home() 可能触发的阻塞,直接取 window_size + c = wda.USBClient(udid, wdaFunctionPort) + size = c.window_size() + print(f"[Screen] 成功获取屏幕 {int(size.width)}x{int(size.height)} {udid}") + return int(size.width), int(size.height), float(c.scale) + except Exception as e: + print(f"[Screen] 获取屏幕信息异常: {e} {udid}") + return 0, 0, 0.0 \ No newline at end of file diff --git a/Utils/ControlUtils.py b/Utils/ControlUtils.py index c2ec417..cbbe1e7 100644 --- a/Utils/ControlUtils.py +++ b/Utils/ControlUtils.py @@ -151,16 +151,31 @@ class ControlUtils(object): @classmethod def clickLike(cls, session: Client, udid): try: - scale = session.scale - x, y = AiUtils.findImageInScreen("add", udid) - print(x, y) - if x > -1: - LogManager.method_info("点赞了", "关注打招呼", udid) - session.click(x // scale, y // scale + 50) - return True + from script.ScriptManager import ScriptManager + + width, height, scale = ScriptManager.get_screen_info(udid) + + if scale == 3.0: + x, y = AiUtils.findImageInScreen("add", udid) + if x > -1: + LogManager.method_info(f"点赞了,点赞的坐标是:{x // scale, y // scale + 50}", "关注打招呼", udid) + session.click(int(x // scale), int(y // scale + 50)) + return True + else: + LogManager.method_info("没有找到目标", "关注打招呼", udid) + return False else: - LogManager.method_info("没有找到目标", "关注打招呼", udid) - return False + x, y = AiUtils.findImageInScreen("like1", udid) + if x > -1: + LogManager.method_info(f"点赞了,点赞的坐标是:{x // scale, y // scale}", "关注打招呼", udid) + session.click(int(x // scale), int(y // scale)) + return True + else: + LogManager.method_info("没有找到目标", "关注打招呼", udid) + return False + + + except Exception as e: LogManager.method_info(f"点赞出现异常,异常的原因:{e}", "关注打招呼", udid) raise False @@ -191,8 +206,6 @@ class ControlUtils(object): # 获取主播详情页的第一个视频 @classmethod def clickFirstVideoFromDetailPage(cls, session: Client): - # videoCell = session.xpath( - # '//Window/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[2]/Other[1]/ScrollView[1]/Other[1]/CollectionView[1]/Cell[2]') videoCell = session.xpath( '(//XCUIElementTypeCollectionView//XCUIElementTypeCell[.//XCUIElementTypeImage[@name="profile_video"]])[1]') diff --git a/Utils/OCRUtils.py b/Utils/OCRUtils.py index c9f2cbe..65e7672 100644 --- a/Utils/OCRUtils.py +++ b/Utils/OCRUtils.py @@ -1,3 +1,5 @@ +import os + import cv2 import numpy as np from typing import List, Tuple, Union, Optional @@ -162,6 +164,15 @@ class OCRUtils: centers: [(cx, cy), ...] boxes: [[x1,y1,x2,y2], ...] (np.ndarray, int) """ + + if not os.path.isfile(template_path): + print(f"模板文件不存在 → {template_path}") + raise FileNotFoundError(f"模板文件不存在 → {template_path}") + + size = os.path.getsize(template_path) + if size == 0: + print(f"模板文件大小为 0 → {template_path} ") + raise ValueError(f"模板文件大小为 0 → {template_path}") # 模板(灰度) template = cv2.imread(template_path, cv2.IMREAD_GRAYSCALE) if template is None: @@ -230,4 +241,4 @@ class OCRUtils: # 全部尝试失败 if return_boxes: return last_centers, last_boxes - return last_centers + return last_centers \ No newline at end of file diff --git a/resources/comment2.png b/resources/comment2.png new file mode 100644 index 0000000000000000000000000000000000000000..fa7a0342b0af73ead4739eb5a015cee9695c3fea GIT binary patch literal 3544 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 M=e?8ulNUSne@coYxBvhE literal 0 HcmV?d00001 diff --git a/resources/insert_comment2x.png b/resources/insert_comment2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2ee2f79b0f7c613c1b1f768eacbb21c2a12d9b34 GIT binary patch literal 3630 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 literal 0 HcmV?d00001 diff --git a/resources/like1.png b/resources/like1.png new file mode 100644 index 0000000000000000000000000000000000000000..db982023a35149fa8b0ced728b8f244202c66b88 GIT binary patch literal 1218 zcmV;z1U>tSP)^y9R|Wg#`Lz_wVr28N1v0Ld#5P>D25e9Lmgl-|y#5U*Gr5v^LvQ z%7dDk8o%E^K0ZD_KfkfD5s5^i(df?3&f?+f9|`#chf1c|SEZlo?j8jr`bw6w%2**YhT0Rc1|4#$&NMyRZ;oSdAD#bPp~ zF-ZJJXuJ89n~I`v{dmE@vXNoXKn5jgnGI*9>)Y?YizUrntNLZds)RR{8>TgC?iOWY@ zm(X*&-O~FpgM)*Gnmk3~I39a<@V(6S?Fmk&vrzN3s33`|w1@uwe%aQlpepSt+EjSi z(5n3K<6NpdXHKNr+S>K?b=lCWpo(zXT}l0UUVI^Z|DHA1pG>s12-U{MM%@5zw!Ug` zn^ju00icSoZVGjDbmZ9IS`AbY&d|5n0)ap>nUoE!3aSX}2GH5rSzhk|!ny%)7k6}Y zBpX^4RNLCxbOZ2uy}P@n?_Ej-stD@_P+woaxw$DDS`}0gPP?nisKa$N7!1mWR%P+m zAj0}Bonrg?o9S|?1E^-Y|3`a!ds(ccNTMq3c?Xm$_Pf7ZeLKYEM-o-(ukro|quf4Q zb0TSz2fdMz5$T;m{U~4e+z5sLwDJJZ6HlCUa91!hGb6iN3G{M4Z&Yk`&)5GG*_Zt+ z0GA&z^rZ7?#>U1hxG##uVu(rCGvQ`ub#+w+C^aZ$+=ZP-cX#*U;h~ICI*>t0T4qIk zu>RrrM;4h#Cy6*RrXR9bRaGr4EXZJ`01afM-}$I3QfX_mR(B1pJlSYzX$gnJGVogMKV>0}D3Mo&*qNp9A(4{pw~WdwDL(f`()dk-R)v&GQ145TAz)-8hx)B#jDt_%ze zoSdA#!irI&p_-TB3MnbS%Y zU3@;Dj8z(x)GtH6{Ob1J-ky{_3z|($O_~1vMiEI@Yro&Wyu2)Z_0XX8mcO7?wos_U za9w+5^7d5t{yp)KFa9veK~B-Ydg^)V9XJ;ReffxMC!SjErVJW)0x_(ySg*;a- gTvL%ppYp%rUp@kjwEm_{M*si-07*qoM6N<$f*o2=C;$Ke literal 0 HcmV?d00001 diff --git a/script/ScriptManager.py b/script/ScriptManager.py index 5674572..590b882 100644 --- a/script/ScriptManager.py +++ b/script/ScriptManager.py @@ -32,6 +32,17 @@ class ScriptManager(): # cls._instance = super(ScriptManager, cls).__new__(cls) # # 返回已存在的实例 # return cls._instance + _device_cache = {} + _cache_lock = threading.Lock() # 线程安全锁(可选,如果你有多线程) + + @classmethod + def get_screen_info(cls, udid: str): + # 如果缓存中没有该设备的信息,则获取并缓存 + if udid not in cls._device_cache: + with cls._cache_lock: # 防止并发写入 + if udid not in cls._device_cache: # 双重检查 + cls._device_cache[udid] = AiUtils._screen_info(udid) + return cls._device_cache[udid] def __init__(self): super().__init__() @@ -40,87 +51,100 @@ class ScriptManager(): current_dir = Path(__file__).resolve().parent # 项目根目录(假设你的类文件在项目的子目录里,比如 Module/OCR/OCRUtils.py) self.lock = threading.Lock() - project_root = current_dir.parent # 如果你确定这个文件就在项目根目录下,可省略这行 # resources 文件夹路径 - # 获取相应的模板的地址 self.resources_dir = project_root / "resources" + + # === 2. @2x 素材 (scale=2) === + self.comment_dir2 = self.resources_dir / "comment2.png" + self.comment_add_dir_2x = self.resources_dir / "insert_comment2x.png" + self.comment_add_dir2_2x = self.resources_dir / "insert_comment2x.png" + + # === 3. @3x 素材 (scale=3) === self.comment_dir = self.resources_dir / "comment.png" self.comment_add_dir = self.resources_dir / "insert_comment.png" self.comment_add_dir2 = self.resources_dir / "insert_comment2.png" + self.initialized = True # 标记已初始化 + def _pick_template(self, scale: float): + """ + scale≈3 -> 返回 @3x 素材,除 3 + 其余默认 @2x 素材,除 2 + """ + if abs(scale - 3.0) < 0.3: # 3x + return (self.comment_dir, + self.comment_add_dir, + self.comment_add_dir2, # 3x 兜底 + 3) # 除数 + else: # 2x(默认) + return (self.comment_dir2, + self.comment_add_dir_2x, + self.comment_add_dir2_2x, # 2x 兜底 + 2) # 除数 + def comment_flow(self, filePath, session, udid, recomend_cx, recomend_cy): - """评论一条龙:点评论框->输入->发送->返回""" + width, height, scale = self.get_screen_info(udid) + + # 取当前分辨率的三张图 + 除数 + comment_tpl, add_tpl, add_fb_tpl, div = self._pick_template(scale) + + # ① 点评论按钮 + coord = OCRUtils.find_template(str(comment_tpl), filePath) + + LogManager.method_info(f"使用的模板路径是:{str(comment_tpl)}", "养号", udid) - coord = OCRUtils.find_template(str(self.comment_dir), filePath) if not coord: - return # 没检测到评论按钮就拉倒 + print("无法检测到评论按钮") + LogManager.method_info("无法检测到评论按钮", "养号", udid) + return - cx, cy = coord[0] # ✅ 注意这里取第一个点 - session.click(int(cx / 3), int(cy / 3)) - - LogManager.method_info(f"点击评论的坐标:{int(cx / 3)}, {int(cy / 3)}", "养号", udid) + cx, cy = coord[0] + session.click(int(cx / div), int(cy / div)) + LogManager.method_info(f"点击评论坐标:{int(cx / div)}, {int(cy / div)}", "养号", udid) time.sleep(2) - # 截图二判(防止键盘弹出后坐标变化) + # ② 重新截图(防止键盘弹起) img = session.screenshot() - time.sleep(2) filePath = os.path.join(os.path.dirname(filePath), "bgv_comment.png") img.save(filePath) - # 从评论列表中随机取出一条数据,进行评论 - if Variables.commentList: - single_comment = random.choice(Variables.commentList) - else: - single_comment = "评论没有导入数据" - - coord2 = OCRUtils.find_template(str(self.comment_add_dir), filePath) + # ③ 随机评论语 + single_comment = random.choice(Variables.commentList) if Variables.commentList else "评论没有导入数据" + # ④ 找「添加评论」按钮 + coord2 = OCRUtils.find_template(str(add_tpl), filePath) click_count = False - - if coord2: # 二判命中 - LogManager.method_info(f"方案1", "养号", udid) + if coord2: # 方案 1 命中 cx2, cy2 = coord2[0] - session.tap(int(cx2 / 3), int(cy2 / 3)) - LogManager.method_info(f"点击添加评论的坐标:{int(cx2 / 3)}, {int(cy2 / 3)}", "养号", udid) + session.tap(int(cx2 / div), int(cy2 / div)) session.send_keys(f"{single_comment}\n") - time.sleep(2) - LogManager.method_info("评论成功", "养号", udid) click_count = True - - else: + LogManager.method_info("评论成功(方案1)", "养号", udid) + else: # 方案 2 兜底 time.sleep(1) - LogManager.method_info(f"方案2", "养号", udid) img = session.screenshot() - filePath = os.path.join(os.path.dirname(filePath), "bgv_comment.png") img.save(filePath) - coord3 = OCRUtils.find_template(str(self.comment_add_dir2), filePath) - if coord3: # 二判命中 + coord3 = OCRUtils.find_template(str(add_fb_tpl), filePath) + if coord3: cx3, cy3 = coord3[0] - session.tap(int(cx3 / 3), int(cy3 / 3)) + session.tap(int(cx3 / div), int(cy3 / div)) session.send_keys(f"{single_comment}\n") - time.sleep(2) - LogManager.method_info("评论成功", "养号", udid) click_count = True + LogManager.method_info("评论成功(方案2)", "养号", udid) - # 点返回/取消按钮:优先用推荐按钮坐标,没有就兜底 100,100 - tap_x = int(recomend_cx) if recomend_cx else 100 - tap_y = int(recomend_cy) if recomend_cy else 100 - if click_count: + # ⑤ 返回 / 取消 + # tap_x = int(recomend_cx) if recomend_cx else 100 + # tap_y = int(recomend_cy) if recomend_cy else 100 - print("点击一次") - LogManager.method_info("点击一次", "养号", udid) + time.sleep(1) - session.tap(tap_x, tap_y) - else: - print("点击两次") - LogManager.method_info("点击两次", "养号", udid) + session.tap(100, 100) - session.tap(tap_x, tap_y) + if not click_count: # 兜底多点一次 time.sleep(1) - session.tap(tap_x, tap_y) + session.tap(100, 100) # 养号 def growAccount(self, udid, isComment, event, is_monitoring=False): @@ -186,10 +210,19 @@ class ScriptManager(): # ---- 视频逻辑 ---- try: - addX, addY = AiUtils.findImageInScreen("add", udid) + width, height, scale = self.get_screen_info(udid) + if scale == 3.0: + addX, addY = AiUtils.findImageInScreen("add", udid) + else: + addX, addY = AiUtils.findImageInScreen("like1", udid) + isSame = False for i in range(2): - tx, ty = AiUtils.findImageInScreen("add", udid) + if scale == 3.0: + tx, ty = AiUtils.findImageInScreen("add", udid) + else: + tx, ty = AiUtils.findImageInScreen("like1", udid) + if addX == tx and addY == ty: isSame = True event.wait(timeout=1) @@ -214,7 +247,7 @@ class ScriptManager(): # 重置 session session.appium_settings({"snapshotMaxDepth": 0}) - if needLike < 23: + if needLike < 25: LogManager.method_info("进行点赞", "养号", udid) ControlUtils.clickLike(session, udid) LogManager.method_info("继续观看视频", "养号", udid) @@ -631,6 +664,7 @@ class ScriptManager(): LogManager.method_info(f"是否进行评论:{isComment}", "关注打招呼", udid) # 使用OCR进行评论 if isComment: + LogManager.method_info("调用方法进行评论", "关注打招呼", udid) self.comment_flow(filePath, session, udid, 100, 100) event.wait(timeout=2) @@ -1590,9 +1624,16 @@ class ScriptManager(): ) # 活动 + # xp_activity_badge = ( + # "//XCUIElementTypeCell[.//XCUIElementTypeLink[@name='活动']]" + # "//XCUIElementTypeStaticText[string-length(@value)>0 and translate(@value,'0123456789','')='']" + # ) xp_activity_badge = ( - "//XCUIElementTypeCell[.//XCUIElementTypeLink[@name='活动']]" - "//XCUIElementTypeStaticText[string-length(@value)>0 and translate(@value,'0123456789','')='']" + "//XCUIElementTypeLink[@name='活动']/ancestor::XCUIElementTypeCell[1]" + "//XCUIElementTypeStaticText[" + " @value and " + " (translate(@value,'0123456789','')='' or @value='99+')" + "]" ) # 系统通知 @@ -1931,11 +1972,12 @@ class ScriptManager(): client = wda.USBClient(udid, ev.wdaFunctionPort) session = client.session() - + width, height, scale = self.get_screen_info(udid) count = 0 while count <= 5: try: + # 重启打开 ControlUtils.closeTikTok(session, udid) time.sleep(1) @@ -2079,8 +2121,12 @@ class ScriptManager(): # 随机偏移(增强拟人) num = random.randint(-10, 10) # 分辨率/坐标映射(按你设备比例;你原来是 /3) - tap_x = int((center_x + num) / 3) - tap_y = int((center_y + num) / 3) + if scale == 3.0: + tap_x = int((center_x + num) / 3) + tap_y = int((center_y + num) / 3) + else: + tap_x = int((center_x + num) / 2) + tap_y = int((center_y + num) / 2) LogManager.method_info(f"点击坐标: ({tap_x}, {tap_y}),账号: {target_account}", "切换账号", udid) session.tap(tap_x, tap_y)