教你用Python写安卓游戏外挂


Posted in Python onJanuary 11, 2018

本次我们选择的安卓游戏对象叫“单词英雄”,大家可以先下载这个游戏。

游戏的界面是这样的:

教你用Python写安卓游戏外挂

通过选择单词的意思进行攻击,选对了就正常攻击,选错了就象征性的攻击一下。玩了一段时间之后琢磨可以做成自动的,通过PIL识别图片里的单词和选项,然后翻译英文成中文意思,根据中文模糊匹配选择对应的选项。

查找了N多资料以后开始动手,程序用到以下这些东西:

PIL:Python Imaging Library 大名鼎鼎的图片处理模块

pytesser:Python下用来驱动tesseract-ocr来进行识别的模块

Tesseract-OCR:图像识别引擎,用来把图像识别成文字,可以识别英文和中文,以及其它语言

autopy:Python下用来模拟操作鼠标和键盘的模块。

安装步骤(win7环境):

(1)安装PIL,下载地址:http://www.pythonware.com/products/pil/,安装Python Imaging Library 1.1.7 for Python 2.7。

(2)安装pytesser,下载地址:http://code.google.com/p/pytesser/,下载解压后直接放在
C:\Python27\Lib\site-packages下,在文件夹下建立pytesser.pth文件,内容为C:\Python27\Lib\site-packages\pytesser_v0.0.1

(3)安装Tesseract OCR engine,下载:https://github.com/tesseract-ocr/tesseract/wiki/Downloads,下载Windows installer of tesseract-ocr 3.02.02 (including English language data)的安装文件,进行安装。

(4)安装语言包,在https://github.com/tesseract-ocr/tessdata下载chi_sim.traineddata简体中文语言包,放到安装的Tesseract OCR目标下的tessdata文件夹内,用来识别简体中文。

(5)修改C:\Python27\Lib\site-packages\pytesser_v0.0.1下的pytesser.py的函数,将原来的image_to_string函数增加语音选择参数language,language='chi_sim'就可以用来识别中文,默认为eng英文。

改好后的pytesser.py:

"""OCR in Python using the Tesseract engine from Google
http://code.google.com/p/pytesser/
by Michael J.T. O'Kelly
V 0.0.1, 3/10/07"""
import Image
import subprocess
import util
import errors
tesseract_exe_name = 'tesseract' # Name of executable to be called at command line
scratch_image_name = "temp.bmp" # This file must be .bmp or other Tesseract-compatible format
scratch_text_name_root = "temp" # Leave out the .txt extension
cleanup_scratch_flag = True # Temporary files cleaned up after OCR operation
def call_tesseract(input_filename, output_filename, language):
 """Calls external tesseract.exe on input file (restrictions on types),
 outputting output_filename+'txt'"""
 args = [tesseract_exe_name, input_filename, output_filename, "-l", language]
 proc = subprocess.Popen(args)
 retcode = proc.wait()
 if retcode!=0:
  errors.check_for_errors()
def image_to_string(im, cleanup = cleanup_scratch_flag, language = "eng"):
 """Converts im to file, applies tesseract, and fetches resulting text.
 If cleanup=True, delete scratch files after operation."""
 try:
  util.image_to_scratch(im, scratch_image_name)
  call_tesseract(scratch_image_name, scratch_text_name_root,language)
  text = util.retrieve_text(scratch_text_name_root)
 finally:
  if cleanup:
   util.perform_cleanup(scratch_image_name, scratch_text_name_root)
 return text
def image_file_to_string(filename, cleanup = cleanup_scratch_flag, graceful_errors=True, language = "eng"):
 """Applies tesseract to filename; or, if image is incompatible and graceful_errors=True,
 converts to compatible format and then applies tesseract. Fetches resulting text.
 If cleanup=True, delete scratch files after operation."""
 try:
  try:
   call_tesseract(filename, scratch_text_name_root, language)
   text = util.retrieve_text(scratch_text_name_root)
  except errors.Tesser_General_Exception:
   if graceful_errors:
    im = Image.open(filename)
    text = image_to_string(im, cleanup)
   else:
    raise
 finally:
  if cleanup:
   util.perform_cleanup(scratch_image_name, scratch_text_name_root)
 return text
if __name__=='__main__':
 im = Image.open('phototest.tif')
 text = image_to_string(im)
 print text
 try:
  text = image_file_to_string('fnord.tif', graceful_errors=False)
 except errors.Tesser_General_Exception, value:
  print "fnord.tif is incompatible filetype. Try graceful_errors=True"
  print value
 text = image_file_to_string('fnord.tif', graceful_errors=True)
 print "fnord.tif contents:", text
 text = image_file_to_string('fonts_test.png', graceful_errors=True)
 print text

(6)安装autopy,下载地址:https://pypi.python.org/pypi/autopy,下载autopy-0.51.win32-py2.7.exe进行安装,用来模拟鼠标操作。

说下程序的思路:

1. 首先是通过模拟器在WINDOWS下执行安卓的程序,然后用PicPick进行截图,将战斗画面中需要用到的区域进行测量,记录下具体在屏幕上的位置区域,用图中1来判断战斗是否开始(保存下来用作比对),用2,3,4,5,6的区域抓取识别成文字。

教你用Python写安卓游戏外挂

计算图片指纹的程序:

def get_hash(self, img):
    #计算图片的hash值
    image = img.convert("L")
    pixels = list(image.getdata())
    avg = sum(pixels) / len(pixels)
    return "".join(map(lambda p : "1" if p > avg else "0", pixels))

图片识别成字符:

#识别出对应位置图像成字符,把字符交给chose处理
  def getWordMeaning(self):
    pic_up = ImageGrab.grab((480,350, 480+300, 350+66))
    pic_aws1 = ImageGrab.grab((463,456, 463+362, 456+45))
    pic_aws2 = ImageGrab.grab((463,530, 463+362, 530+45))
    pic_aws3 = ImageGrab.grab((463,601, 463+362, 601+45))
    pic_aws4 = ImageGrab.grab((463,673, 463+362, 673+45))
    str_up = image_to_string(pic_up).strip().lower()
    #判断当前单词和上次识别单词相同,就不继续识别
    if str_up <> self.lastWord:
      #如果题目单词是英文,选项按中文进行识别
      if str_up.isalpha():
        eng_up = self.dt[str_up].decode('gbk') if self.dt.has_key(str_up) else ''
        chs1 = image_to_string(pic_aws1, language='chi_sim').decode('utf-8').strip()
        chs2 = image_to_string(pic_aws2, language='chi_sim').decode('utf-8').strip()
        chs3 = image_to_string(pic_aws3, language='chi_sim').decode('utf-8').strip()
        chs4 = image_to_string(pic_aws4, language='chi_sim').decode('utf-8').strip()
        print str_up, ':', eng_up
        self.chose(eng_up, (chs1, chs2, chs3, chs4))
      #如果题目单词是中文,选项按英文进行识别
      else:
        chs_up = image_to_string(pic_up, language='chi_sim').decode('utf-8').strip()
        eng1 = image_to_string(pic_aws1).strip()
        eng2 = image_to_string(pic_aws2).strip()
        eng3 = image_to_string(pic_aws3).strip()
        eng4 = image_to_string(pic_aws4).strip()
        
        e2c1 = self.dt[eng1].decode('gbk') if self.dt.has_key(eng1) else ''
        e2c2 = self.dt[eng2].decode('gbk') if self.dt.has_key(eng2) else ''
        e2c3 = self.dt[eng3].decode('gbk') if self.dt.has_key(eng3) else ''
        e2c4 = self.dt[eng4].decode('gbk') if self.dt.has_key(eng4) else ''
        print chs_up
        self.chose(chs_up, (e2c1, e2c2, e2c3, e2c4))
      self.lastWord = str_up
    return str_up

2. 对于1位置的图片提前截一个保存下来,然后通过计算当前画面和保存下来的图片的距离,判断如果小于40的就表示已经到了选择界面,然后识别2,3,4,5,6成字符,判断如果2位置识别成英文字符的,就用2解析出来的英文在字典中获取中文意思,然后再通过2的中文意思和3,4,5,6文字进行匹配,匹配上汉字最多的就做选择,如果匹配不上默认返回最后一个。之前本来考虑是用Fuzzywuzzy来进行模糊匹配算相似度的,不过后来测试了下对于中文匹配的效果不好,就改成按汉字单个进行匹配计算相似度。

匹配文字进行选择:

#根据传入的题目和选项进行匹配选择
  def chose(self, g, chs_list):
    j, max_score = -1, 0
    same_list = None
    #替换掉题目里的特殊字符
    re_list = [u'~', u',', u'.', u';', u' ', u'a', u'V', u'v', u'i', u'n', u'【', u')', u'_', u'W', u'd', u'j', u'-', u't']
    for i in re_list:
      g = g.replace(i, '')
    print type(g)
    #判断2个字符串中相同字符,相同字符最多的为最佳答案
    for i, chsWord in enumerate(chs_list):
      print type(chsWord)
      l = [x for x in g if x in chsWord and len(x)>0]
      score = len(l) if l else 0
      
      if score > max_score:
        max_score = score
        j = i
        same_list = l
    #如果没有匹配上默认选最后一个
    if j ==-1:
      print '1. %s; 2. %s; 3. %s; 4. %s; Not found choice.' % (chs_list[0], chs_list[1], chs_list[2], chs_list[3])
    else:
      print '1. %s; 2. %s; 3. %s; 4. %s; choice: %s' % (chs_list[0], chs_list[1], chs_list[2], chs_list[3], chs_list[j])
      for k, v in enumerate(same_list):
        print str(k) + '.' + v,
    order = j + 1
    self.mouseMove(order)
    return order

3.最后通过mouseMove调用autopy操作鼠标点击对应位置进行选择。

程序运行的录像:http://v.youku.com/v_show/id_XMTYxNTAzMDUwNA==.html

程序完成后使用正常,因为图片识别准确率和字典的问题,正确率约为70%左右,效果还是比较满意。程序总体来说比较简单,做出来也就是纯粹娱乐一下,串联使用了图片识别、中文模糊匹配、鼠标模拟操作,算是个简单的小外挂吧,源程序和用到的文件如下:

http://git.oschina.net/highroom/My-Project/tree/master/Word%20Hero

Python 相关文章推荐
Python实现建立SSH连接的方法
Jun 03 Python
python爬取亚马逊书籍信息代码分享
Dec 09 Python
Django 2.0版本的新特性抢先看!
Jan 05 Python
Python设计模式之MVC模式简单示例
Jan 10 Python
Python爬虫实现(伪)球迷速成
Jun 10 Python
Django中使用Celery的教程详解
Aug 24 Python
Python网页正文转换语音文件的操作方法
Dec 09 Python
Python字典添加,删除,查询等相关操作方法详解
Feb 07 Python
Python中断多重循环的几种方式详解
Feb 10 Python
什么是python的列表推导式
May 26 Python
Python如何使用ConfigParser读取配置文件
Nov 12 Python
pycharm 的Structure界面设置操作
Feb 05 Python
python实现学生管理系统
Jan 11 #Python
linecache模块加载和缓存文件内容详解
Jan 11 #Python
Python实现将MySQL数据库表中的数据导出生成csv格式文件的方法
Jan 11 #Python
python+django+sql学生信息管理后台开发
Jan 11 #Python
hmac模块生成加入了密钥的消息摘要详解
Jan 11 #Python
快速了解Python中的装饰器
Jan 11 #Python
简单了解python模块概念
Jan 11 #Python
You might like
CakePHP去除默认显示的标题及图标的方法
2008/10/22 PHP
PHP数据库调用类调用实例(详细注释)
2012/07/12 PHP
php数组(array)输出的三种形式详解
2013/06/05 PHP
php实现图片等比例缩放代码
2015/07/23 PHP
PHP-FPM之Chroot执行环境详解
2015/08/03 PHP
iOS10推送通知开发教程
2016/09/19 PHP
学习ExtJS 访问容器对象
2009/10/07 Javascript
jquery插件 cluetip 关键词注释
2010/01/12 Javascript
TextArea设置MaxLength属性最大输入值的js代码
2012/12/21 Javascript
JavaScript 模块的循环加载实现方法
2015/12/13 Javascript
深入理解JS中的substr和substring
2016/04/26 Javascript
原生JS取代一些JQuery方法的简单实现
2016/09/20 Javascript
js+html5实现侧滑页面效果
2017/07/15 Javascript
用最少的JS代码写出贪吃蛇游戏
2018/01/12 Javascript
javaScript产生随机数的用法小结
2018/04/21 Javascript
使用vue-cli打包过程中的步骤以及问题的解决
2018/05/08 Javascript
VUE在for循环里面根据内容值动态的加入class值的方法
2018/08/12 Javascript
nodejs log4js 使用详解
2019/05/31 NodeJs
js实现一款简单踩白块小游戏(曾经很火)
2019/12/02 Javascript
python3 与python2 异常处理的区别与联系
2016/06/19 Python
使用python根据端口号关闭进程的方法
2018/11/06 Python
Python 动态变量名定义与调用方法
2020/02/09 Python
Jupyter notebook快速入门教程(推荐)
2020/05/18 Python
Django通过设置CORS解决跨域问题
2020/11/26 Python
C有"按引用传递"吗
2016/09/06 面试题
大专计算机个人求职的自我评价
2013/10/21 职场文书
革命先烈的英雄事迹材料
2014/02/15 职场文书
科长竞聘演讲稿
2014/05/16 职场文书
航海技术专业毕业生推荐信
2014/07/09 职场文书
2015幼儿园庆元旦活动方案
2014/12/09 职场文书
慰问信范文
2015/02/14 职场文书
2015年建党94周年演讲稿
2015/03/19 职场文书
承兑汇票延期证明
2015/06/23 职场文书
SQL Server2019数据库之简单子查询的具有方法
2021/04/27 SQL Server
vue实现拖拽交换位置
2022/04/07 Vue.js
Win11显卡控制面板打开显卡设置方法
2022/04/20 数码科技