• 隐藏侧边栏
  • 展开分类目录
  • 关注微信公众号
  • 我的GitHub
  • QQ:1753970025
Chen Jiehua

百万英雄,让程序自动帮你答题 

目录

最近全民互动直播答题游戏可谓十分火热,只要十二道题目全部回答正确,就能瓜分当场的百万现金大奖。听着是不是跃跃欲试?不过作为一个爱折腾的程序员,当然得另辟蹊径寻找最佳的自动答题解决方案啦!

前言

我们以《百万英雄》作为实验对象来进行尝试,每道题的如图:

每道题目在屏幕中间上方,一般有3~4个选项。所以我们基本的流程确定为:

  1. 手机截屏、裁剪题目和选项;
  2. OCR文字识别,将截图题目和选项转换为文字;
  3. 搜索题目,匹配答案;
  4. 模拟屏幕点击,自动选择答案;

屏幕截图

现在基本每个手机都有屏幕截图的功能,不过手工操作显然不能在限定的时间内完成任务,所以我们需要借助程序来自动化这个流程。

以Android手机为例,我们可以使用ADB(Android Debug Bride),ADB是连接Android手机与PC端的桥梁,通过adb可以管理、操作模拟器和设备,如安装软件、查看设备软硬件参数、系统升级、运行shell命令等。

在Android系统内,截图的命令为 screencap。配合adb,我们可以执行命令:

# 调用screencap命令进行截屏并将图片保存 /sdcard/a.png
$ adb shell screencap -p /sdcard/a.png

然后,我们再把图片从手机传回PC端:

# 把截图从手机/sdcard/a.png上传到PC当前目录
$ adb pull /sdcard/a.png .

然后使用PIL从截屏中裁剪题目和选项:

#!/usr/bin/env python

import io
from PIL import Image

# 边距
width, height = 720, 1280
border_width = 35
border_top = 140
border_bottom = 640
area = (border_width, border_top, width-border_width, border_bottom)


def crop_img(screen_path):
    img = Image.open(screen_path)
    img = img.crop(area)
    buf = io.BytesIO()
    img.save(buf, format="PNG")
    return buf.getvalue()

这样我们通过 crop_img 就可以得到题目和选项的图片了。

OCR文字识别

一提到OCR文字识别,我们立马就可以想到使用开源工具 tesseract 。在Ubuntu下,使用apt-get 安装 tesseract 十分简单,同时也要记得安装 tesseract-chi_sim 的数据包,这里就不详细说明了。

在python下,我们可以使用pyocr第三方库来调用tesseract:

#!/usr/bin/env python

import pyocr

tool = pyocr.get_available_tools()[0]
img = crop_img("a.png")
text = tool.image_to_string(img, lang="chi_sim+eng")

当然,我们在这里直接将题目和选项同时进行识别,其实也可以在上一步截图处理的时候将题目和选项拆开来分别进行识别。

搜索答案

得到了题目的内容,当然直接上百度搜索一下啦。不过难道还要我们一步一步慢慢地打开浏览器、复制粘贴、搜索吗?显然我们不需要这么做,通过使用selenium我们将一切自动化!

Selenium是一个针对网络应用的自动化测试工具,它可以控制浏览器模拟人的操作进行各种测试。它支持各种浏览器,包括 Chrome、Safari、Firefox 等主流界面式浏览器,每个浏览器都有对应的driver。比如我们使用chrome,则需要下载chromedriver

然后我们就可以使用浏览器来搜索题目和答案了:

#!/usr/bin/env python

from selenium import webdriver

# 加载chromedriver
driver = webdriver.Chrome("chromedriver")
# 打开网页百度题目
driver.get("https://www.baidu.com/s?wd=" + question)
# 查看网页源代码
page = driver.page_source
for ans in answers:
    # 统计每一个答案的次数
    print(page.count(ans))

这样子,我们就知道了该题目每个选项出现的次数了。一般而言,出现次数越多代表着答案正确的可能性就越高。

自动答题

既然我们已经确定了答案,那就要赶快在限定时间内选择答案。继续使用ADB工具来在Android手机上模拟点击:

# 模拟点击屏幕(x, y)的位置
$ adb shell input tap x y

当然,对应每一个选项点击的位置稍微计算一下就出来了。

延伸优化

通过上面的几个步骤,我们已经基本实现了整个自动答题的功能。在实践中,我们可能会遇到一些需要优化的地方。

1:Android真机连接PC,使用ADB获取屏幕截图比较慢,耗时2~3秒?

其实我们完全可以使用Android模拟器来进行屏幕截图,实践中发现模拟器截图大概只要0.5秒就可以完成操作。

2:OCR文字识别中,Tesseract出现错别字或识别不完整,导致后续题目检索困难?

可以换一个更成熟的OCR识别方案,或者使用第三方提供的文字识别API。可以试试百度的OCR接口,我测试了感觉OK。

3:Chromedriver每次调用打开感觉也挺慢的?

可以使用PhantomJS,它是一个基于webkit的没有界面的浏览器,效率更高。

4:最近微信跳一跳也挺火的,能不能刷刷分?

原理类似,计算出每一跳的距离,对应触摸屏幕的时间,然后用ADB来模拟屏幕操作。

码字很辛苦,转载请注明来自ChenJiehua《百万英雄,让程序自动帮你答题》

评论