python 答题辅助_如何在百万英雄直播答题中使用Python辅助?

本文介绍了使用Python结合OCR技术和adb工具,实现直播答题辅助的方法。通过开启多个手机模拟器,截图并识别题目,利用搜索策略判断答案,最终通过adb控制模拟器选择答案。虽然存在OCR识别准确率和搜索时间的问题,但该方法提供了一种自动化答题的思路。
摘要由CSDN通过智能技术生成

首先写这个辅助的想法来源于之前微信小游戏“跳一跳”的辅助,使用到了adb来获得手机的截图等,而直播答题碰到不会的题遇到的困难主要就是没时间去打字搜索,如果用同样的方法得到了题目相关的文字信息自动去搜索,成功率不就大大提高了嘛!再有很自然想到的一点就是一道题就3个选项,3台手机不就肯定能保证对一道吗?因此如何快速操作多个手机模拟器也需要考虑。

028e532cb08c

效果图

Ref

思路

开启多个手机模拟器,题目出现时启动Python程序,截图并进行OCR识别出文字,获得各个选项,接着对问题以及各个选项分别进行搜索,获得前几条搜索结果或者页面数量等进行判断。

手机模拟器

在这里我用的是夜神手机模拟器,需要用到一个分辨率、DPI较高的模拟器用于OCR识别,剩下的配置尽量调低降低硬件开销。

028e532cb08c

手机模拟器多开

adb

由于需要操作多个模拟器,我们首先需要知道如何连接各个模拟器。下载好adb包之后将其配置到环境变量中,然后adb devices查询在线的模拟器即可。然而有时候模拟器抽风,这个命令不起作用,这个时候需要先adb connect之后adb devices才有用(神设定),查看对应安装目录,Nox\bin\debug.bat发现查找对应模拟器的端口的方法是通过查找配置文件的5555端口实现的,依葫芦画瓢,来到Nox\bin\BignoxVMS查看各个副本的配置文件即可得到端口。这里总结一下用到的adb命令

//输入adb可查看相关命令用法

//存在多个模拟器时需要用-s 指定操作的目标

adb -s 127.0.0.1:62001 shell screencap -p /sdcard/n.png //截屏

adb -s 127.0.0.1:62001 pull /sdcard/n.png ./n.png //传到电脑

//输入adb shell input可查看相关命令用法

adb -s 127.0.0.1:62001 shell input tap x y //点击(x,y)位置 用以点击问题的选项

确定题目与选项位置

经过测试题目选项出现的位置是固定的,所以这里的问题主要是将分辨率较高的模拟器上选项的位置对应到低分辨率模拟器上。

028e532cb08c

分辨率480X800 DPI 160

028e532cb08c

分辨率480X800 DPI 60

028e532cb08c

分辨率240X400 DPI 60

从以上3张图可以得到,分辨率相同的话,题目区域大小与DPI成正比;DPI相同的话,整个题目占用的像素点是相同的,题目区域大小与分辨率成反比。所以假如在480X800 DPI 160的模拟器上位置为(x,y),在240X400 DPI 60的模拟器上位置为(x,y*2*60/160)=(x,0.75y)

028e532cb08c

相对关系

OCR

从固定位置中裁剪出问题的图像,再OCR识别为文字。这里用到的是tesseract-ocr,同样需要配置环境变量。

系统变量下添加变量TESSDATA_PREFIX值为E:\Tesseract-OCR\tessdata

PATH下添加E:\Tesseract-OCR

还需要下载一个中文的数据包chi_sim.traineddata放到E:\Tesseract-OCR\tessdata

cmd下输入tesseract test.png out.txt -l chi_sim生成的out.txt即为test.png的识别结果。需要注意这个test.png需要裁剪出待识别的区域,否则效果很差。

以上步骤成功后就可以用Python的pytesseract库来返回结果了。

# 保存问题

cropped_img = im[y_start:y_end, x_start:x_end]

cv2.imwrite("total.bmp" , cropped_img)

# 这里直接使用cropped_img不行,需要保存后再用PIL.Image打开

text_result=pytesseract.image_to_string(Image.open("total.bmp"), lang="chi_sim"a

搜索策略

文本拿到就很好做了。预处理一下,然后用jieba获取问题的关键词,再进行搜索就行啦。这里我用的是根据搜索结果的数目来判断的。这里请参考Wikipedia ——Pointwise mutual information

divided=text.replace(" ","").split("\n")

for i in divided:

if (i=="" or i=="\n"):

divided.remove(i)

question=divided[0]

del divided[0]

print("Question: %s"%question)

keywords=jieba.analyse.extract_tags(question,topK=2,withWeight=True)

print("Keywords:")

for i in keywords:

print i

totalweight=0

print ("Options: ")

print("\n".join(divided))

至于说获得搜索结果的数量,用一个Xpath来提取就好啦,相信大家写过爬虫之后很容易搞定的。

def get_search_nums(word):

# url="https://www.baidu.com/s?wd="+unicode(word,"utf-8")

#需要先转为utf8才能进行quote

url="https://www.baidu.com/s?wd="+urllib2.quote(word.encode("utf8"))

myheaders = {

'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"} # 浏览器请求头

request=urllib2.Request(url,headers=myheaders)

response=urllib2.urlopen(request)

source=response.read()

html=etree.HTML(source)

result=html.xpath('''//*[@id="container"]/div[2]/div/div[2]/text()''')

result=result[0]

pattern=re.compile(u".*约([\d,]+)个")

#!!!注意这里编码和网页返回的编码要对应才可以进行查找!!大坑!

num=re.findall(pattern,result)

num=int(num[0].replace(",",""))

return num

结果

嗯…用这种PMI算法得到的结果还是不太靠谱,按照整个问题来搜索AC选项差异不大,按照“电影”这个关键词应该选B……(正确答案是C)所以还是需要把搜索结果的前几条给展示出来的。获得正确答案之后朝着各个模拟器发送一个对应位置的adb shell input去点击选项即可。

028e532cb08c

答案应该为第七艺术

改进

OCR效果太差导致搜索出错。如上图的“第六艺术”识别为“第大艺术”(啥玩意儿啊)在Ref中的第二篇文章中用到了百度的OCR,不知道效果如何。

搜索多个页面由于网络速度的限制还是比较费时间的。

“跳一跳”中曾出现直接抓包分析并提交结果的方法,不知道在西瓜视频里面能否用上。

使用多个模拟器测试的过程中发现各个问题在模拟器上的出现是有时差的,延后出现对作答是有利的,能否在可接受的范围内加大这个时差?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值