现在短视频横行的时代,以某短视频为首的,背后依靠着强大的资金后盾,疯狂地对平台用户进行红包轰炸。shell
与传统的红包不同,视频红包包含位置的不肯定性、大小不肯定性、元素 ID 的不肯定性等......这些不肯定性都会致使抢红包的操做变得异常的复杂。app
本篇文章的目的是利用 Python 自动化实现「抢视频红包」这一骚操做。异步
ps:本文仅用做学习交流,请勿用于其余用途。ide
在开始编写脚本以前,须要作以下准备工具
一、一部 Android 手机,并在 PC 端配置好 ADB 运行环境学习
二、Python 虚拟环境下安装自动化依赖库、图片对比依赖库测试
三、PS 或者其余图片编辑软件ui
# 自动化依赖 pip3 install pocoui # 图片对比依赖 pip3 install aircv
第一步,咱们须要借助 Airtest 驱动手机打开目标短视频 App。线程
# 目标应用的包名和LaunchActivity self.package_name = 'com.**.weishi' self.home_activity = 'com.**.oscar.module.splash.SplashActivity' # 回到主界面 home() # stop_app(self.package_name) # 打开应用 start_my_app(self.package_name, self.home_activity)
第一次打开应用的时候,会弹出一个警告对话框。3d
这里利用「异步线程」去处理。
循环检测对话框元素是否存在,一旦出现,就模拟点击操做,关闭这个对话框。
def __handle_dialog(self): """ 处理警告对话框 :return: """ count = 0 while count < self.wait_for_dialog_timeout: tip_notice = self.poco('com.tencent.weishi:id/title_text', text=u'青少年保护功能提示') try: if tip_notice.exists(): # 关闭 print('出现警告对话框,关闭之。') self.poco('com.tencent.weishi:id/close_btn').click() break else: pass except Exception as e: print('产生异常了') time.sleep(1) count += 1 # 异步处理 threading.Thread(target=self.__handle_dialog, name='thread1').start()
第二步,「判断」当前播放的视频是不是一个包含红包的视频。
经过对大量视频的观察,能够看出视频内包含两类红包,分别是普通视频红包、问答视频红包。
经过 Android SDK 自动的工具 Monitor 查看界面元素。
惋惜的是,这个互动红包元素标识「元素 ID 不存在」,而且 Text 属性也为空,无法利用传统的方式来获取到。
我换一种方式来实现,利用「图片对比」技术来判断互动红包元素是否存在,进而判断视频是不是一个包含红包的视频。
利用「PS」把互动红包元素图片从屏幕截图中裁剪出来。
须要注意的是,因为这个元素形状不规则,这里只能裁剪一个规则的矩形区域,不能截取其余多余的区域,不然会致使图片比对会失败。
接着利用 adb 命令截取手机屏幕的图片,而后保存到本地。
def save_screenshot_to_pc(desc): """ 获取屏幕截图 desc 截图保存路径 :return: """ exec_cmd('adb shell /system/bin/screencap -p /sdcard/screenshot.png') exec_cmd('adb pull /sdcard/screenshot.png %s' % desc)
而后就能够利用「aircv」库,利用上面裁剪的图和屏幕截图进行比对,判断裁剪的互动红包元素是否能匹配到。
当匹配指数为 0.8 以上的时候,就认为当前视频内必定包含红包。
def find_image(source_path, part_path): """ 匹配模板 :param source_path: 原图片 :param part_path: 待匹配的图片 :return: """ # 原始图像 source = ac.imread(source_path) # 待查找的部分 part = ac.imread(part_path) result_raw = ac.find_template(source, part) # 匹配图片中心点坐标 if result_raw and result_raw.get('confidence') >= 0.8: center_position = result_raw.get('result') print(result_raw) else: center_position = None return center_position
第三步,若是判断当前视频内包含互动红包元素,就能够执行「抢红包」的操做了。
首先,利用 Monitor 截取红包出现那一刻的界面元素树,依然能够看到红包图片元素不存在 ID 和 Text 属性。
而后我首先想到是否能够利用上面的方式,经过局部图片匹配去拿到红包图片的中心点坐标。
但是经过大量的测试发现,视频中红包图片元素的大小「存在不肯定性」,用 PS 截取的图片不能适用于全部视频。
最后,只能经过分析元素的层次结构,拿到存在元素 ID 的最近一级父类元素,而后再去获得红包元素,进而获得「bound」属性值。
vp = self.poco('com.tencent.weishi:id/hippy_container') if vp.exists(): # 元素 try: red_package_element = vp.children()[0].children()[0].children()[0].children()[0] except Exception: print('产生一个异常') continue # 获取bound()属性 element_size = red_package_element.get_bounds()
拿到红包图片元素的 bound 属性以后,就能够计算出红包图片元素的中心点坐标。
def get_element_center_position(poco, bound): """ 获取元素的中心点坐标 :return: """ # 获取手机屏幕的宽、高 screen_width = poco.get_screen_size()[0] screen_height = poco.get_screen_size()[1] # 元素的中心点坐标 center_position = (bound[1] + bound[-1]) / 2 * screen_width, ( bound[0] + bound[2]) / 2 * screen_height return center_position
咱们都知道一段视频中,红包出现的时间存在不肯定性。
经过对红包图片出现前和出现后的元素树进行对比,能够发现,当红包出现的时候,红包图片元素「存在多个子元素」。
所以能够循环获取 UI 元素树,直到红包元素存在子元素的时候,就退出循环。
# 一直等待红包元素出现,才执行点击操做 if len(red_package_element.children()) > 0: print(center_position) break else: # print('等待红包出现能够点击') pass
经过点击红包元素的「中心点坐标」,就能够完成抢视频红包的最后操做。
# 获取到红包坐标以后,执行点击点击操做,直到抢到红包为止 exec_cmd('adb shell input tap %d %d' % (center_position[0], center_position[1]))
经过上面的操做,完成了抢普通视频红包的操做,循环操做就能够拿到应用内的全部的普通视频红包。
针对问答视频红包,利用 Monitor 能够直接拿到题目和答案的文本内容,这须要针对题目内容和答案进行一次匹配。
我已经将源码上传到后台上,关注公众号后回复「 ws 」便可得到下载连接。
若是你以为文章还不错,请你们点赞分享下。你的确定是我最大的鼓励和支持。
推荐阅读:
要抢红包?Python来帮你~
薅羊毛 | 让Python天天帮你薅一个早餐钱
THANDKS
-End -