NO.22——用adb实现python机器人帮你找到抖音上的漂亮小姐姐

     

             身边人不断被抖音神曲洗脑,并且深夜狂刷小视频的同僚大有人在,不甘落伍,本人也下载下来一探究竟,果然满屏的漂亮小姐姐。但是自己动手一遍一遍下划实在费劲,结合github上的项目,心想是否可以用Python实现一个douyin_bot帮我完成这些事情,比如关注、点赞、下载小视频。

   

目录

       需求分析

        工作原理

      使用方法

     工作步骤

1、Appium自动化配置

2、Mitmproxy流量分析

3、连接腾讯人脸识别API 

 4、主要程序

结果展示


         

       需求分析

  • 自动翻页
  • 颜值检测
  • 人脸识别
  • 自动关注
  • 自动点赞
  • 小视频下载
  • 随机防Ban

        工作原理

  1. mitmproxy抓包分析:在同一局域网内,手机端打开抖音短视频APP,电脑监听8080端口流量
  2. 手机截屏,并对截图进行压缩(size<1MB)
  3. 请求腾讯AI的人脸识别API接口
  4. 解析返回的人脸JSON信息,对人脸进行切割检测
  5. 当颜值大于某个阈值(美丽程度)时,关注、点赞、下载小视频来一套。
  6. 继续翻页,重复执行第2-5步骤

      使用方法

  1. 获取源码    git clone https://github.com/wangshub/Douyin-Bot.git
  2. 进入源码目录       cd    Douyin-Bot-master
  3. 安装包库     pip install -r requirements.txt
  4. 连接在同一局域网,开启mitmdump截取抖音小视频请求
  5. 手机电脑链接,进入目录,运行程序   douyin-bot.py,进行自动测试

     工作步骤

1、Appium自动化配置

       本人以honor magic手机为例,在设置中调试出开发者模式与电脑相连。在Appium操作界面,配置抖音APP的各项参数如图

          其中appPackage和appActivity两个参数的配置见我之前的blog :Appium参数配置 。然后开始 Start Session

           因为要做自动化测试,所以要模拟点击事件,因此需要记录屏幕主要控件所在的平面坐标 ,记录点赞、关注按钮的XY坐标。

2、Mitmproxy流量分析

          Mitmproxy是手机抓包分析工具,具体使用方法参见上一批blog Mitmproxy抓包分析,在这篇文章里,已经分析出了抖音小视频的URL路径:

         根据mitmdump展示的请求,前缀分别为

                   'http://v1-dy.ixigua.com/', 'http://v9-dy.ixigua.com/',
                   'http://v6-dy.ixigua.com' , 'http://v3-dy-z.ixigua.com/',
                   'http://v3-dy-x.ixigua.com/' , 'http://v3-dy-y.ixigua.com/',
                   'http://v7.pstatp.com/'

         这七类前缀的URL正是我们目标抖音视频的URL 。

        代码如下:

import requests
# 文件路径
path = '/Users/Macx/Desktop/python_demo/Douyin-Bot-master/video/'
num = 1

#使用mitmdump和python脚本拦截http请求和处理flow.request.url,用def response(flow)
def response(flow):
    global num
    # 经测试发现视频url前缀主要是7个
    target_urls = ['http://v1-dy.ixigua.com/', 'http://v9-dy.ixigua.com/',
                   'http://v6-dy.ixigua.com' , 'http://v3-dy-z.ixigua.com/',
                   'http://v3-dy-x.ixigua.com/' , 'http://v3-dy-y.ixigua.com/',
                   'http://v7.pstatp.com/' ]
    #依次从以上7个URL中选出一个进行迭代
    for url in target_urls:
        # 过滤掉不需要的url。如果拦截的http请求是以以上URL为开头
        if flow.request.url.startswith(url):
            # 设置视频名
            filename = path + str(num) + '.mp4'
            # 使用request获取视频url的内容
            # stream=True作用是推迟下载响应体直到访问Response.content属性
            res = requests.get(flow.request.url, stream=True)
            # 将视频写入文件夹
            with open(filename, 'ab') as f:
                f.write(res.content)
                f.flush()
                print(filename + '下载完成')
            num += 1

3、连接腾讯人脸识别API 

     登陆腾讯AI开放平台创建应用

         官网下载SDK ,并引入apiutil.py文件,参考官网

     进行修改后:

#-*- coding: UTF-8 -*-
import hashlib
import urllib
from urllib import parse
import urllib.request
import base64
import json
import time

url_preffix='https://api.ai.qq.com/fcgi-bin/'


def setParams(array, key, value):
    array[key] = value


def genSignString(parser):
    uri_str = ''
    for key in sorted(parser.keys()):
        if key == 'app_key':
            continue
        uri_str += "%s=%s&" % (key, parse.quote(str(parser[key]), safe=''))
    sign_str = uri_str + 'app_key=' + parser['app_key']

    hash_md5 = hashlib.md5(sign_str.encode('utf-8'))
    return hash_md5.hexdigest().upper()


class AiPlat(object):
    def __init__(self, app_id, app_key):
        self.app_id = app_id
        self.app_key = app_key
        self.data = {}
        self.url_data = ''

    def invoke(self, params):
        self.url_data = urllib.parse.urlencode(params).encode("utf-8")
        #利用urlopen()方法可以实现最基本请求的发起,但这几个简单的参数并不足以
        #构建一个完整的请求,如果请求中需要加入headers(请求头)等信息,我们就可以利用
        #更强大的Request类来构建一个请求
        #如req = urllib.request.Request(url=url,data=data,method='POST')
        #req.add_headers('User-Agent','Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36')
        req = urllib.request.Request(self.url, self.url_data)
        try:
            #rsp为针对请求获得的响应,为字典格式
            rsp = urllib.request.urlopen(req)
            str_rsp = rsp.read().decode('utf-8')
            dict_rsp = json.loads(str_rsp)
            return dict_rsp
        except Exception as e:
            print(e)
            return {'ret': -1}

    def face_detectface(self, image, mode):
        self.url = url_preffix + 'face/face_detectface'
        setParams(self.data, 'app_id', self.app_id)
        setParams(self.data, 'app_key', self.app_key)
        setParams(self.data, 'mode', mode)
        setParams(self.data, 'time_stamp', int(time.time()))
        setParams(self.data, 'nonce_str', int(time.time()))
        image_data = base64.b64encode(image)
        setParams(self.data, 'image', image_data.decode("utf-8"))
        sign_str = genSignString(self.data)
        setParams(self.data, 'sign', sign_str)
        return self.invoke(self.data)

 4、主要程序

# -*- coding: utf-8 -*-
"""
    使用Appium做自动化模拟测试
"""
import sys
import random
import time
from PIL import Image


if sys.version_info.major != 3:
    print('Please run under Python3')
    exit(1)
try:
    from common import debug, config, screenshot, UnicodeStreamFilter
    from common.auto_adb import auto_adb
    from common import apiutil
    from common.compression import resize_image
except Exception as ex:
    print(ex)
    print('请将脚本放在项目根目录中运行')
    print('请检查项目根目录中的 common 文件夹是否存在')
    exit(1)

VERSION = "0.0.1"

# 申请地址 http://ai.qq.com
AppID = '1107029674'
AppKey = 'fW0via1sILxB7K4o'

DEBUG_SWITCH = True
FACE_PATH = 'face/'

adb = auto_adb()
adb.test_device()
config = config.open_accordant_config()

# 审美标准
BEAUTY_THRESHOLD = 80

# 最小年龄
GIRL_MIN_AGE = 18


def yes_or_no():
    """
    检查是否已经为启动程序做好了准备
    """
    while True:
        yes_or_no = str(input('请确保手机打开了 ADB 并连接了电脑,'
                              '然后打开手机软件,确定开始?[y/n]:'))
        if yes_or_no == 'y':
            break
        elif yes_or_no == 'n':
            print('谢谢使用', end='')
            exit(0)
        else:
            print('请重新输入')


def _random_bias(num):
    """
    random bias
    :param num:
    :return:
    """
    print('num = ', num)
    return random.randint(-num, num)


def next_page():
    """
    翻到下一页
    :return:
    """
    #模拟滑动,从x1,y1经历durationg时间滑动到x2,y2
    cmd = 'shell input swipe {x1} {y1} {x2} {y2} {duration}'.format(
        x1=config['center_point']['x'],
        y1=config['center_point']['y']+config['center_point']['ry'],
        x2=config['center_point']['x'],
        y2=config['center_point']['y']-config['center_point']['ry'],
        duration=200
    )
    adb.run(cmd)
    time.sleep(2.0)


def follow_user():
    """
    关注用户
    :return:
    """
    #模拟点击
    cmd = 'shell input tap {x} {y}'.format(
        x=config['follow_bottom']['x'] + _random_bias(10),
        y=config['follow_bottom']['y'] + _random_bias(10)
    )
    adb.run(cmd)
    time.sleep(0.5)


def thumbs_up():
    """
    点赞
    :return:
    """
    cmd = 'shell input tap {x} {y}'.format(
        x=config['star_bottom']['x'] + _random_bias(10),
        y=config['star_bottom']['y'] + _random_bias(10)
    )
    adb.run(cmd)
    time.sleep(0.5)


def main():
    """
    main
    :return:
    """
    print('程序版本号:{}'.format(VERSION))
    print('激活窗口并按 CONTROL + C 组合键退出')
    debug.dump_device_info()
    screenshot.check_screenshot()

    while True:
        next_page()

        time.sleep(0.5)
        #通过以下方法获得截图autojump.png
        screenshot.pull_screenshot()
        #通过以下方法对截图进行压缩,得到optimized.png
        resize_image('autojump.png', 'optimized.png', 1024*1024)

        with open('optimized.png', 'rb') as bin_data:
            image_data = bin_data.read()
        #初始化AiPlat
        ai_obj = apiutil.AiPlat(AppID, AppKey)
        #调用AiPlat的face_detectface方法,生成字典形式的rsp,存放图片信息及图片
        rsp = ai_obj.face_detectface(image_data, 0)

        major_total = 0
        minor_total = 0
        #若调用成功。ret返回0,调用成功,非0失败
        if rsp['ret'] == 0:
            beauty = 0
            for face in rsp['data']['face_list']:
                print(face)
                #标注脸部区域
                face_area = (face['x'], face['y'], face['x']+face['width'], face['y']+face['height'])
                print(face_area)
                img = Image.open("optimized.png")
                #对脸部进行切割
                cropped_img = img.crop(face_area).convert('RGB')
                cropped_img.save(FACE_PATH + face['face_id'] + '.png')
                # 性别判断
                if face['beauty'] > beauty and face['gender'] < 50:
                    beauty = face['beauty']

                if face['age'] > GIRL_MIN_AGE:
                    major_total += 1
                else:
                    minor_total += 1

            # 是个美人儿~关注点赞走一波
            if beauty > BEAUTY_THRESHOLD and major_total > minor_total:
                print('发现漂亮妹子!!!')
                thumbs_up()
                follow_user()

        else:
            print(rsp)
            continue


if __name__ == '__main__':
    try:
        # yes_or_no()
        main()
    except KeyboardInterrupt:
        adb.run('kill-server')
        print('谢谢使用')
        exit(0)

结果展示

下载的小视频:

   至于自动点赞、关注什么的就不录制视频了,亲测可以,让程序飞一会儿》》》》》》

猜你喜欢

转载自blog.csdn.net/ghl1390490928/article/details/81429563