Python部落冲突自动搜索对手

2018-07-08  本文已影响0人  Zincox

每次在部落冲突搜索对手,都要花上不少时间。尤其是在发展中期的时候,特别难搜索到肥猪。像我本身的十本大号,在十本中期发展。前期还好,搜到的基本上是十本初的死鱼,随随便便就是五六十万。后来把兵营什么的升级上来,杯一冲到大师杯后,搜索到的基本上是各种十几万,打一把亏一把。搜个几十分钟都不一定碰到一个肥的。作为一个时间就是生命的码农,这肯定是难以接受的,所以就抽空写了这个脚本。

思路

首先要保证的一点是:一定不能封号。好不容易玩了两年发展到十本,封号了岂不是凉凉?所以从原理上,坚决不能读取内存数据。读内存数据相当容易翻车。
所以只能另辟蹊径,走文字识别这条路。原理大概是:

平台选择

由于获取截图需要一定的系统权限,因此平台只能选定安卓平台。在安卓平台下允许使用adb命令连接Android系统截图,并将截图发送到Mac或Windows上来,进行其他的逻辑判断。

截图获取

获取截图可以使用安卓的虚拟机、模拟器,在Windows和Mac下均有相应的Android虚拟机。但如果使用模拟器运行部落冲突,意味着搜索到对手也必须在模拟器下发动进攻。而模拟器下对多指操控很不友好。而且模拟器运行占用资源也会比较大,毕竟码农,还是不希望电脑卡顿的,因此最后选定使用实体机来跑。

好在我有一个闲置下来的小米5,因此可以通过获取小米5的截图,来判断对手资源,发现合适的肥猪再进行提醒。这样也能在手机上操控,最大限度保证能够榨干肥猪。

前期准备

Python

首先你得有一个Python,毕竟这是一个Python脚本。同时还要选择一个好的IDE,这里我选择的是Pycharm。这样在写代码的时候能够省下不少功夫。
Python和Pycharm的安装我就不啰嗦了,百度上一大把。需要注意的是Python最好选择Python3版本,这里我选择的是Python3.6版本,2.7版本在库和语法上与3.6略有不同。

pip

因为需要使用一些Python库,使用pip的安装必不可少。同理,百度一大把。不过安装完成后记得换为国内源,这样下载速度会快很多很多。

https://www.jianshu.com/p/9d986bc8ba69

注册百度的AI文字识别服务

注册完成后开通相应的服务,拿到AppID、API Key和Secret Key就行。后续需要使用到百度的文字识别服务来识别资源。

_apikey_1530979649_2147066274.png

图形处理库Pillow

获取到的屏幕截图还包含有其他文字,这些文字不是所需要的,所以需要使用图形处理库将资源数据裁剪出来,再通过文字识别转换为数字,这样大大提高了识别的精度和效率。

pip install Pillow

我在Mac下安装提示各种缺失,根据缺失将缺失的模块(MySQL-python)补上即可。


_图片中还含有其他文字_1531030593_729756971.png

安卓手机

理论上只要是安卓手机基本都OK,版本在4.4以上的、能够启用开发者选项的就行。因为adb工具需要使用开发者选项来操控手机,所以需要启动开发者选项。不同手机有不同启用方法,具体就不详细赘述了,百度手机型号+启用开发者选项基本都能够搜索到。启用开发者选项后,在开发者选项中启用USB调试即可。

注意:开启前务必关闭关闭(最好卸载)360、毒霸等各种国产安卓软件,关闭其他不必要的优化软件,否则这些软件有权限在你手机上乱搞,比如安装各种乱七八糟的软件,所以开启前务必关闭!!!

_启用usb调试_1531044449_422037486.png

adb工具环境配置

在Mac的终端或Windows的命令提示符下输入

adb --version

如果能过显示相应的adb版本号,如

Android Debug Bridge version 1.0.40
Version 4797878
Installed as /Users/zinc/Library/Android/sdk/platform-tools/adb

则说明adb环境已经配置完毕。否则需要配置环境

Windows系统下比较方便,百度adb工具箱下载即可,大小10mb左右,再根据教程配置adb环境即可

https://jingyan.baidu.com/article/17bd8e52f514d985ab2bb800.html

在Mac下的配置相对比较麻烦,我个人倾向于安装Android Studio,这样能够集成adb工具,也会自动配置好adb环境。如果安装完成后仍未配置好,参照:

https://blog.csdn.net/wwf0123/article/details/52497885

代码实战

首先需要弄清楚总一个流程:

因此分出三个类,ScreenCapturer类负责获取屏幕截图、以及模拟点击操作,PicScanner类负责图片处理、以及上传识别,而autoFind则进行逻辑处理,控制整个流程

ScreenCapturer.py

from os import *
from time import sleep

# adb shell screencap -p /sdcard/1.png(保存到SDCard)
# adb pull /sdcard/screenshot.png d:/screenshot.png(保存到电脑)

class ScreenCapturer:

    # 获取的截图文件在手机中的保存位置(默认保存在内置存储根目录下)
    ANDRIOD_PIC_PATH = "/sdcard/screenshot.png"
    # 文件保存在电脑中的目录
    TRANS_PIC_PATH = "/Users/zinc/Documents/autoFind/screenshot.png"
    # 获取截图的adb命令
    SCREEN_CAP_CMD = "adb shell screencap -p "
    # 传输文件至电脑adb命令
    TRANS_FILE_CMD = "adb pull "
    # 获取Android手机分辨率命令
    GET_RESOLUTION_CMD = "adb shell dumpsys window displays"
    # 模拟点击命令
    POINT_SCREEN_CMD = "adb shell input tap"
    # 手机分辨率
    phoneResolution = []

    def __init__(self,andriod="",trans=""):
        if andriod!="" and trans != "":
            # 判断是否为默认参数
            self.ANDRIOD_PIC_PATH = andriod
            self.TRANS_PIC_PATH = trans

    def getPhoneScreen(self):
        # 获取屏幕截图
        command = self.SCREEN_CAP_CMD + self.ANDRIOD_PIC_PATH
        system(command)

    def transPhoneScreen(self):
        # 将截图传输至电脑
        command = self.TRANS_FILE_CMD + self.ANDRIOD_PIC_PATH + " " +self.TRANS_PIC_PATH
        system(command)
        print("截图已获取")

    # 模拟点击某一位置
    def pointOnPhone(self,x=0.0,y=0.0):
        strX = str(x)
        strY = str(y)
        command = self.POINT_SCREEN_CMD + " " + strX + " " + strY
        system(command)
        pass
    
    # 获取屏幕分辨率
    def getPhoneResolution(self):
        # 获取命令行的打印值
        r = popen(self.GET_RESOLUTION_CMD)
        text = str(r.read())
        # 查找init=字符串,其后为手机分辨率情况
        beginC = text.find("init=")
        # 获取其后的10个字符
        line = text[beginC+5:beginC+15]
        resolution = line.split("x")
        self.phoneResolution.append(float(resolution[0]))
        self.phoneResolution.append(float(resolution[1]))
        print("weight =",self.phoneResolution[0],"\nheight =",self.phoneResolution[1])
        r.close()
        pass
    
    # 点击进攻按钮
    def pointAttackBtn(self):
        # 保留两位小数
        x = 0.07 * self.phoneResolution[1]
        y = 0.9 * self.phoneResolution[0]
        self.pointOnPhone(x,y)
        print("点击进攻按钮")
    
    # 点击搜索对手按钮
    def pointSearchAttacker(self):
        # 保留两位小数
        x = 0.23 * self.phoneResolution[1]
        y = 0.72 * self.phoneResolution[0]
        self.pointOnPhone(x, y)
        print("点击搜索对手按钮")

    # 点击搜索下一个按钮
    def pointNextAttacker(self):
        # 保留两位小数
        x = 0.925 * self.phoneResolution[1]
        y = 0.732 * self.phoneResolution[0]
        self.pointOnPhone(x, y)
        print("点击搜索下一个按钮")

    # 点击结束战斗按钮
    def pointEndAttack(self):
        # 保留两位小数
        x = 0.075 * self.phoneResolution[1]
        y = 0.745 * self.phoneResolution[0]
        self.pointOnPhone(x, y)
        print("点击结束战斗按钮")


# 测试代码,完成类的测试后注释

# capture = ScreenCapturer()
#
# capture.getPhoneScreen()
# capture.transPhoneScreen()

# capture.getPhoneResolution()
# capture.pointAttackBtn()
# capture.pointSearchAttacker()
# for i in range(0,5):
#     sleep(5)
#     capture.pointNextAttacker()
# sleep(5)
# capture.pointEndAttack()

去掉最底部的测试注释,直接运行ScreenCapturer.py,测试功能是否正常

一些常量的注释

ANDRIOD_PIC_PATH = "/sdcard/screenshot.png"
TRANS_PIC_PATH = "/Users/zinc/Documents/autoFind/screenshot.png"

PicScanner.py

from aip import AipOcr
from PIL import Image

class PicScanner:

    """ 你的 APPID AK SK """
    APP_ID = '这里填写百度AI的APPID'
    API_KEY = "百度AI的API_KEY"
    SECRET_KEY = "百度AI的SECRET_KEY"

    # 初始化AipFace对象
    # aipOcr = AipOcr(APP_ID, API_KEY, SECRET_KEY)

    # 定义参数变量
    options = {
        'detect_direction': 'true',
        'language_type': 'CHN_ENG',
    }

    # 读取图片
    # 文件保存在电脑中的目录
    filePath = "/Users/zinc/Documents/autoFind/screenshot.png"

    def __init__(self,path=""):
        if path!="":
            self.filePath = path

    def get_file_content(self,filePath):
        with open(filePath, 'rb') as fp:
            return fp.read()

    def readPicNum(self,path=""):
        if path != "":
            self.filePath = path
        aipOcr = AipOcr(self.APP_ID, self.API_KEY, self.SECRET_KEY)
        # 调用通用文字识别接口
        result = aipOcr.basicAccurate(self.get_file_content(self.filePath), self.options) # 高精度
        #result = aipOcr.basicGeneral(self.get_file_content(self.filePath), self.options) # 高速
        return result

        # 将截图裁剪至仅剩资源的部分,方便于图片识别
    def cutPicToSource(self):
        im = Image.open(self.filePath, 'r')
        if im:
            width, height = im.size
            cropedIm = im.crop((0.046 * width, 0.125 * height, 0.135 * width, 0.268 * height))
            cropedIm.save(self.filePath)
        else:
            print("图片文件打开失败")

# scanner = PicScanner()
# # scanner.cutPicToSource()
# scanner.readPicNum()
    APP_ID = '这里填写百度AI的APPID'
    API_KEY = "百度AI的API_KEY"
    SECRET_KEY = "百度AI的SECRET_KEY"
result = aipOcr.basicAccurate(self.get_file_content(self.filePath), self.options) # 高精度
#result = aipOcr.basicGeneral(self.get_file_content(self.filePath), self.options) # 高速
# 将截图裁剪至仅剩资源的部分,方便于图片识别
def cutPicToSource(self):
im = Image.open(self.filePath, 'r')
# 检测是否打开成功
if im:
    width, height = im.size
    cropedIm = im.crop((0.046 * width, 0.125 * height, 0.135 * width, 0.268 * height))
    cropedIm.save(self.filePath)
else:
    print("图片文件打开失败")

autoFind.py

from PicScanner import PicScanner
from ScreenCapturer import ScreenCapturer
from time import sleep
import tkinter
import tkinter.messagebox

class autoFind:

    # 对象实例
    scanner = PicScanner()
    capture = ScreenCapturer()
    # 设置的搜索资源值
    source = {}
    # 获取到的资源值
    int_gold = 0
    int_water = 0
    int_black = 0

    def setSourceValue(self,gold,water,black_w):
        self.source['gold'] = gold
        self.source['water'] = water
        self.source['black_w'] = black_w
        print(self.source)

    def beginFind(self):
        self.showAdvice()
        # 获取屏幕分辨率
        self.capture.getPhoneResolution()
        # 点击进攻按钮
        self.capture.pointAttackBtn()
        # 点击搜索对手按钮
        self.capture.pointSearchAttacker()
        # 延时5s
        sleep(6)
        while(1):
            # 获取屏幕截图并判断资源
            self.capture.getPhoneScreen()
            self.capture.transPhoneScreen()
            self.scanner.cutPicToSource()
            words = self.scanner.readPicNum()
            words_result = words['words_result']
            # 尝试获取资源,如果抛出异常则说明获取失败
            try:
                gold = words_result[0]['words']
                water = words_result[1]['words']
                black_w = words_result[2]['words']
            except:
                print("获取资源失败,开始搜索下一个对手")
                sleep(2)
                continue
            # 尝试将其转换为整数,转换失败则说明识别失败
            try:
                print("当前搜索到的对手资源为",gold, water, black_w)
                self.int_gold = int(gold)
                print(self.int_gold)
                self.int_water = int(water)
                print(self.int_water)
                self.int_black = int(black_w)
                print(self.int_black)
            except:
                print("资源识别失败,搜索下一个对手")
                self.capture.pointNextAttacker()
                sleep(6)
                continue
            # 如果能够成功转化,则判断资源值是否满足设定值
            if self.int_gold > self.source['gold'] and self.int_water > self.source['water'] and self.int_black > self.source['black_w']:
                self.findVictim(str(self.int_gold), str(self.int_water), str(self.int_black))
                # 发现肥猪跳出循环
                break
            else:
                # 如果不满足设定值,则继续搜索下一个对手
                print("这个人是个穷b,懒得打他了")
                self.capture.pointNextAttacker()
                sleep(6)

    # 找到合适对手后进行提醒
    def findVictim(self,gold,water,black_w):
        tkinter.messagebox.showinfo('发现肥猪', '找到一个肥猪,他有'+gold+"金币,"+water+"圣水和"+black_w+"重油,搜索程序已暂停.")

    def showAdvice(self):
        tkinter.messagebox.showinfo('使用前准备', "使用前先回到大本营界面,搜索过程中不要点击其他按钮,搜索到对手后会自动暂停。点击确定开始进行搜索")

find = autoFind()
try:
    find.setSourceValue(300000,300000,1000)
    find.beginFind()
except:
    tkinter.messagebox.showinfo('程序出错!', "程序出错!已暂停搜索,请返回大本营重新运行程序!")

运行效果

_搜索到的肥猪_1531047047_1147857544.png _搜索到对手_1531046946_1261457288.png

Just Enjoy!

所以以后就不需要不停地盯着屏幕看了,虽然可能会漏鱼,不过也大大节省了时间,以后只要边看视频别挂着搜肥猪,遇到肥猪就打就行。

上一篇下一篇

猜你喜欢

热点阅读