• 使用python编写微信跳一跳的自动脚本


    实现思路:

    1. 调用adb命令,截图
    2. 寻找小小人的底部中心点role(从下到上扫描,直到找到小小人相同像素的点,至于小小人像素点rgb是什么,可以使用photoshop查看)
    3. 寻找棋盘最高点top,然后寻找棋盘最右点。根据最高点与最右点,确定棋盘中心点border
    4. 计算role与border之间的直线距离,然后设置按压时间=距离*按压系数
    5. 调用adb 命令,按压屏幕

    完整代码,测试机Oppo r11

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    from PIL import Image, ImageDraw
    import math
    import os
    import time
    import subprocess
    
    # 小小人底部RGB
    role_bottom_rgb = (58, 58, 102)
    # 小小人头部RGB
    role_top_rgb = (65, 65, 90)
    # 白色中心点 RGB
    white_point = (245, 245, 245)
    # 按压系数
    press_coefficient = 1.35
    
    
    def get_screenshot():
        """
        获取截图信息
        :return:
        """
    
        process = subprocess.Popen('adb shell screencap -p', shell=True,
                                   stdout=subprocess.PIPE)
        binary_screenshot = process.stdout.read()
        binary_screenshot = binary_screenshot.replace(b'
    
    ', b'
    ')
        with open('autojump.png', 'wb') as f:
            f.write(binary_screenshot)
        time.sleep(1)
        img = Image.open('autojump.png')
        return img
    
    
    def is_similar(rgb1, rgb2, degree=20):
        """
        判断颜色是否相近
        :param rgb1:
        :param rgb2:
        :param degree:
        :return:
        """
        return abs(rgb1[0] - rgb2[0]) <= degree and abs(
            rgb1[1] - rgb2[1]) <= degree and abs(rgb1[2] - rgb2[2]) <= degree
    
    
    def calculate_jump_distance(img):
        """
        计算跳一跳的距离
        :param image:
        :return:
        """
        draw = ImageDraw.Draw(img)
        im_pixel = img.load()
        w, h = img.size
        # 设置有效扫描区域
        min_x = 100
        max_x = w - 10
        min_y = 400
        max_y = h - 100
        # step1:寻找小小人底座位置
        role_start_x = 0
        role_end_x = 0
        role_y = 0
        find_role = False
        # y轴从下往上扫描
        for y in range(max_y, min_y, -1):
            # 找到小小人最低部一行,退出y轴循环
            if find_role:
                break
            # y轴未找到最低一行,则继续遍历x轴元素点
            # x轴从左到右扫描
            for x in range(min_x, max_x):
                current_rgb = im_pixel[x, y]  # 当前像素RGB值
                # 寻找到小人底座首位像素点
                if is_similar(current_rgb, role_bottom_rgb, 5):
                    if not find_role:  # 找到首位像素点
                        find_role = True
                        role_start_x = x
                        role_y = y  # 小人底座中心点的y轴坐标已确定
    
                # 小人底座最右侧像素点定位,条件:首位像素点已找到,在当前y轴上继续遍历x轴,当当前像素不在小小人中时,前一个像素点为底座最右点
                if find_role and not is_similar(current_rgb, role_bottom_rgb, 5):
                    role_end_x = x - 1
                    break
        # 小小人底座中心点
        role_x = (role_start_x + role_end_x) / 2
        role = (role_x, role_y)
        draw.point([role], fill=(255, 0, 0))
    
        # step2:寻找棋盘顶点:从上往下,从左到右扫描,寻找首位与初始点不一样的像素
        # 解决小小人头部出现在最顶部时的BUG,在x轴扫描时,跳过小小人位置[role_start_x,role_end_x]
        top_x = 0
        top_y = 0
        top_rgb = None
        role_top_flag = False
        for y in range(min_y, max_y):
            for x in range(min_x, max_x):
                current_rgb = im_pixel[x, y]
                # 首先出现小小人的头部
                if not role_top_flag:
                    if is_similar(current_rgb, role_top_rgb, 40):
                        print("首先出现小小人头部!")
                        role_top_flag = True
                        continue
                        # 当小小人头部在最顶部时,从上到下扫描时,当x处于小小人位置中时,跳过本次循环
                if (role_start_x - 50 <= x <= role_end_x + 50) and role_top_flag:
                    # 当x轴坐标在小小人位置时
                    continue
    
                # 顶部既不是小小人,又与初始像素点不一样,则定位为棋盘顶部,退出x轴扫描
                if not is_similar(current_rgb, im_pixel[min_x, min_y],
                                  20):  # 与背景像素点不一样
                    top_x = x
                    # 解决棋盘边上出现一条乱七八糟颜色点将棋盘围起来时的BUG,找到第一个差异点后y轴继续往下5个像素点作为顶点
                    top_y = y + 4
                    top_rgb = im_pixel[top_x, top_y]
                    break
    
            if top_rgb:  # 找到与初始点不一样的像素点,退出y轴循环
                break
    
        top = (top_x, top_y)
        draw.point([top], fill=(255, 0, 0))
    
        # step3:寻找棋盘最右侧点,条件:从top_x 向右,top_y 向下扫描,当与棋盘顶部像素点相似,x轴最大时,所在点为最右点
        right_x = top_x
        right_y = top_y
        find_border = False
        check_rgb = top_rgb
        for x in range(top_x, max_x):
            for y in range(top_y, max_y):
                current_rgb = im_pixel[x, y]
                # 找到相邻的相似元素点,定位条件:30个像素内,颜色相似
                if is_similar(current_rgb, check_rgb, 20) and abs(
                                x - right_x) <= 5 and abs(y - right_y) <= 5:
                    check_rgb = current_rgb
                    find_border = True
                    right_x = x
                    right_y = y
                    break
            else:
                # 如果当前y轴扫描完毕都没有遇到棋盘相似点(即没有遇到break),说明已经超出了最右侧棋盘点,退出x轴循环
                if find_border:
                    break
        right = (right_x, right_y)
        draw.point([right], fill=(255, 0, 0))
        # step4:定位棋盘中心:扫描棋盘,判断是否存在中心白点,否则初略可认为棋盘中心点位置是顶点和右侧点交叉位置
        border = (top_x, right_y)
        # 先排除初略中心点位置与白色中心点相似的情况,否则遇到白色版面会定位错误
        if not is_similar(im_pixel[top_x, right_y], white_point, 4):
            find_white_point = False
            for y in range(top_y + 5, right_y + 5):
                for x in range(top_x * 2 - right_x + 5, right_x - 5):
                    if is_similar(im_pixel[x, y], white_point, 2):
                        # 寻找到白色中心点
                        find_white_point = True
                        border = (x, y + 10)
                        print("寻找到白色中心点!")
                        break
                # 寻找到白色中心点,退出y轴循环
                if find_white_point:
                    break
        draw.point([border], fill=(255, 0, 0))
    
        # draw.line([top, right], fill=(255, 0, 0), width=10)
        draw.line([role, top, right, border], fill=(255, 0, 0), width=10)
        # img.show()
        img.save("debug.png")
        return math.sqrt((role[0] - border[0]) ** 2 + (role[1] - border[1]) ** 2)
    
    
    def jump(distance):
        press_time = distance * press_coefficient
        press_time = max(press_time, 200)  # 设置 200ms 是最小的按压时间
        press_time = int(press_time)
        cmd = 'adb shell input swipe 400 400 400 400 {duration}'.format(
            duration=press_time)
        print(cmd)
        os.system(cmd)
        return press_time
    
    
    if __name__ == '__main__':
        i = 1
        # img = get_screenshot()
        # img=Image.open('autojump.png')
        # distance = calculate_jump_distance(img)
        # img.close()
        # jump(distance)
    
        while True:
            img = get_screenshot()
            distance = calculate_jump_distance(img)
            jump(distance)
            img.close()
            i += 1
            if i == 10:
                time.sleep(2)
            time.sleep(2)
            print("*" * 100)
    ***微信扫一扫,关注“python测试开发圈”,了解更多测试教程!***
  • 相关阅读:
    unity代码加密for Android,mono编译
    php __invoke 和 __autoload
    VC只运行一个程序实例
    VC单文档对话框添加托盘图标
    技术文档应该怎么写
    项目管理学习
    cannot download, /home/azhukov/go is a GOROOT, not a GOPATH
    Go语言学习
    appium键盘事件
    appium-doctor
  • 原文地址:https://www.cnblogs.com/guanfuchang/p/8318323.html
Copyright © 2020-2023  润新知