美文网首页自动化测试
薅羊毛 | Python 带你抢视频红包,不放过一个红包!

薅羊毛 | Python 带你抢视频红包,不放过一个红包!

作者: AirPython | 来源:发表于2019-09-20 09:42 被阅读0次
    image

    阅读文本大概需要 15 分钟。

    1、目 标 场 景

    如今短视频横行的时代,以某短视频为首的,背后依靠着强大的资金后盾,疯狂地对平台用户进行红包轰炸。

    image

    与传统的红包不一样,视频红包包含位置的不确定性、大小不确定性、元素 ID 的不确定性等......这些不确定性都会导致抢红包的操作变得异常的复杂。

    本篇文章的目的是利用 Python 自动化实现「抢视频红包」这一骚操作。

    ps:本文仅用作学习交流,请勿用于其他用途。

    2、准 备 工 作

    在开始编写脚本之前,需要做如下准备

    1、一部 Android 手机,并在 PC 端配置好 ADB 运行环境

    2、Python 虚拟环境下安装自动化依赖库、图片对比依赖库

    3、PS 或者其他图片编辑软件

    # 自动化依赖
    pip3 install pocoui
    
    # 图片对比依赖
    pip3 install aircv
    

    3、编 写 代 码

    第一步,我们需要借助 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)
    

    第一次打开应用的时候,会弹出一个警告对话框。

    image

    这里利用「异步线程」去处理。

    循环检测对话框元素是否存在,一旦出现,就模拟点击操作,关闭这个对话框。

    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()
    

    第二步,「判断」当前播放的视频是否是一个包含红包的视频。

    通过对大量视频的观察,可以看出视频内包含两类红包,分别是普通视频红包、问答视频红包。

    image

    通过 Android SDK 自动的工具 Monitor 查看界面元素。

    可惜的是,这个互动红包元素标识「元素 ID 不存在」,并且 Text 属性也为空,没法利用传统的方式来获取到。

    image

    我换一种方式来实现,利用「图片对比」技术来判断互动红包元素是否存在,进而判断视频是否是一个包含红包的视频。

    利用「PS」把互动红包元素图片从屏幕截图中裁剪出来。

    需要注意的是,由于这个元素形状不规则,这里只能裁剪一个规则的矩形区域,不能截取其他多余的区域,否则会导致图片比对会失败。

    image

    接着利用 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 属性。

    image

    然后我首先想到是否可以利用上面的方式,通过局部图片匹配去拿到红包图片的中心点坐标。

    image

    可是通过大量的测试发现,视频中红包图片元素的大小「存在不确定性」,用 PS 截取的图片不能适用于所有视频。

    image

    最后,只能通过分析元素的层次结构,拿到存在元素 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 属性之后,就可以计算出红包图片元素的中心点坐标。

    image
    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]))
    

    4、结 果 结 论

    通过上面的操作,完成了抢普通视频红包的操作,循环操作就可以拿到应用内的所有的普通视频红包。

    针对问答视频红包,利用 Monitor 可以直接拿到题目和答案的文本内容,这需要针对题目内容和答案进行一次匹配。

    我已经将全部源码上传到公众号后台上,关注公众号「 AirPython 」后回复「 ws」即可获得下载链接。

    如果你觉得文章还不错,请大家点赞分享下。你的肯定是我最大的鼓励和支持。

    推荐阅读:

    要抢红包?Python来帮你~

    薅羊毛 | 让Python每天帮你薅一个早餐钱

    相关文章

      网友评论

        本文标题:薅羊毛 | Python 带你抢视频红包,不放过一个红包!

        本文链接:https://www.haomeiwen.com/subject/bbsductx.html