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)

結果展示

下載的小視頻:

   至於自動點贊、關注什麼的就不錄製視頻了,親測可以,讓程序飛一會兒》》》》》》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章