社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

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

Python数据科学 • 7 年前 • 727 次点击  

点击上方“Python数据科学”,星标公众号

重磅干货,第一时间送达


☞500g+超全学习资源免费领取,干货来袭!

作者:星果安 转自:AirPython


1

目 标 场 景


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



与传统的红包不一样,视频红包包含位置的不确定性、大小不确定性、元素 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)


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



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


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


def __handle_dialog(self):
    """
    处理警告对话框
    :return:
    """

    count = 0
    while count          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]))



4

结 果 结 论


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


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


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


如果你觉得文章还不错,请大家点个「在看」支持下。你的肯定是我最大的鼓励和支持。



/ 今日留言赠送书籍 /

☞  混脸熟赠书规则

《机器学习线性代数基础-Python语言描述》

👆扫描上方二维码购买


内容介绍:数学是机器学习绕不开的基础知识,传统教材的风格偏重理论定义和运算技巧,想以此高效地打下机器学习的数学基础,针对性和可读性并不佳。本书以机器学习涉及的线性代数核心知识为重点,进行新的尝试和突破:从坐标与变换、空间与映射、近似与拟合、相似与特征、降维与压缩这5个维度,环环相扣地展开线性代数与机器学习算法紧密结合的核心内容,并分析推荐系统和图像压缩两个实践案例,在介绍完核心概念后,还将线性代数的应用领域向函数空间和复数域中进行拓展与延伸;同时极力避免数学的晦涩枯燥,充分挖掘线性代数的几何内涵,并以Python语言为工具进行数学思想和解决方案的有效实践。 

  《机器学习线性代数基础:Python语言描述》适合实践于数据分析、信号处理等工程领域的读者,也适合在人工智能、机器学习领域进行理论学习和实践,希望筑牢数学基础的读者,以及正在进行线性代数课程学习的读者阅读。



/ 上期中奖者公布 /
恭喜Wind同学上期走心留言中奖,
获取《机器学习线性代数基础-Python语言描述》书籍一本,
请联系小编获取,微信:lucici1990



推荐阅读
1、接私活必备的 10 个开源项目!

2、Python 最强编辑器详细使用指南!

3、听完阿里BI述说的苦水,我很有同感!
4、技术面试时该反问面试官什么问题?小伙整理了灵魂50问,GitHub日入2500星
5、2019互联网月饼哪家强?阿里走情怀;百度最土豪!


👆关注“数据挖掘工程师”

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/43469