python识别文字答题_头脑王者的Python答题助手——从OCR文字识别到Fiddler抓包
由于自己的专业不是学计算机的,所以只能利用课余时间自学Python。从上个暑假开始,写了大大小小的Python小程序,虽然大多数都比较简陋,但确实在每一次写代码的时候都能感受到编程的乐趣。
最近微信的小游戏占据了很多人的朋友圈,像跳一跳、头脑王者。自从上次体验了知乎大神写的跳一跳辅助程序之后,自己就有了做一个头脑王者答题助手的念头,一开始也是希望能够实现全自动答题,仿照跳一跳那个adb+Python的模式。看了网络上的一些教程,大多数教程都是比较简单的,没有完整代码,仅仅提供一个思路,那就自己动手丰衣足食吧~~
1.OCR文字识别
一开始接触到的就是OCR,经过百度谷歌之后,Python识别图片的文字需要pytesseract和PIL两个库,还需要识别引擎tesseract-ocr。前面两个库通过命令行安装就好了,然后tesseract可以在github下载,在安装的过程中记得要选择下载简体中文的语言包。安装完成之后,需要修改一下配置才能正常使用,找到你Python的安装路径,打开Python\Lib\site-packages\pytesseract\pytesseract.py,打开之后,作以下修改:
#tesseract_cmd = 'tesseract'
tesseract_cmd = 'C:/Program Files (x86)/Tesseract-OCR/tesseract.exe'
成功之后我们找一道题来试一下:
from PIL import Image
import pytesseract
question = pytesseract.image_to_string(Image.open('test.jpeg'),lang='chi_sim')
question = question.replace(' ','') #去除空格
print(question)
OK~虽然有一些错别字,但是至少是识别出来了。看到成功识别出题目之后,我就兴奋地去写接下去的代码,可是后来用不同的题目来测试代码的时候,才发现识别率是真的低,除了一开始兵马俑那道题,其他题测试出来全是乱码。无奈只能去谷歌提高识别率的方法,网络上都是说黑白图片、高分辨率图片的识别率会高一点。后来就加了一段修改图片的代码,都是运用了PIL这个库。
修改图片模式:
from PIL import Image
img = img.convert('1')
裁剪图片(从手机截图裁剪题目的部分):
from PIL import Image
p = Image.open(picname)
p_size = p.size #获得图片尺寸
t = p.crop((0,int(p_size[1])*0.25,p_size[0],int(p_size[1])*0.45)) #截取题目部分的图片,后两个数字要比前两个大
但是修改之后,识别率并没有明显的变化,大多数图片识别出来还是乱码,在停滞了一段时间之后(主要还是因为学习期末很多事做- -),突然想到修改图片的背景颜色和字体的颜色,经过多次检验,发现黄底黑字的识别率最高,颜色改了之后,大多数的题目都能识别出来了。
图片修改颜色:
from PIL import Image
t2 = t1.convert('RGB') #转rgb模式
for i in range(0,t2.size[0]):
for j in range(0,t2.size[1]):
r = t2.getpixel((i,j))[0]
g = t2.getpixel((i,j))[1]
b = t2.getpixel((i,j))[2]
if b>r and b>g and (r,g<100)and (b<210):
r=255
g=255
b=154 #背景蓝色变黄
elif (r,g,b>=180):
b=0 #白色字变黑
g=0
r=0
t2.putpixel((i,j), (r,g,b))
代码大概的思路是用ADB命令实时截取头脑王者的图片,然后处理图片,识别出题目和四个选项,用百度知道搜索题目,再用爬虫抓下答案,根据四个选项在答案中的出现次数,得出最佳选项。
完整代码:
from PIL import Image
import pytesseract
import requests
from bs4 import BeautifulSoup as BS
from urllib import parse
import datetime
import os
def open_pic(picname):
p = Image.open(picname)
p_size = p.size #获得图片尺寸
t = p.crop((0,int(p_size[1])*0.25,p_size[0],int(p_size[1])*0.45)) #截取题目部分的图片,后两个数字要比前两个大
t.save('./first_change.png')
t_size = t.size #获得截取后的图片尺寸
return t_size,p,t
def get_question(picsize,firstpic):
new_x = 0
new_y = 0
t = firstpic
for i in range(0,picsize[0]):
last_pixel = t.getpixel((i,0))[2]
for j in range(0,picsize[1]):
now_pixel = t.getpixel((i,j))[2]
if last_pixel < 190 and now_pixel > 200:
new_x = i-50
new_y = j-150
break
if new_x:
break #找到背景和文字刚刚转换的像素点
#背景变黄色,字体变黑色 t1 = t.crop((new_x,new_y,new_x+894,new_y+280))
t2 = t1.convert('RGB') #转rgb模式
for i in range(0,t2.size[0]):
for j in range(0,t2.size[1]):
r = t2.getpixel((i,j))[0]
g = t2.getpixel((i,j))[1]
b = t2.getpixel((i,j))[2]
if b>r and b>g and (r,g<100)and (b<210):
r=255
g=255
b=154 #背景蓝色变黄
elif (r,g,b>=180):
b=0 #白色字变黑
g=0
r=0
t2.putpixel((i,j), (r,g,b))
t2.save("./second_change.png")
question = pytesseract.image_to_string(Image.open('second_change.png'),lang='chi_sim') #分析题目
question = question.replace(' ','') #去除空格
question = question.replace('\n','') #去除换行
print(question)
return question
def get_choice(oldpic):
p = oldpic
p_size = p.size
c = p.crop((250,int(p_size[1])*11/20,850,int(p_size[1])*8/9)) #截取选项部分的图片,后两个数字要比前两个大
c1 = c.crop((0,0,600,691*1/6))
c2 = c.crop((0,160,600,300))
c3 = c.crop((0,360,600,500))
c4 = c.crop((0,550,600,691))
cc = [c1,c2,c3,c4]
choices = []
for h in cc:
for i in range(0,h.size[0]):
for j in range(0,h.size[1]):
r = h.getpixel((i,j))[0]
g = h.getpixel((i,j))[1]
b = h.getpixel((i,j))[2]
if b>r and b>g and (r,g<100)and (b<220):
r=0
g=0
b=0 #蓝色字变黑
elif (r,g,b>=160):
b=154 #白色背景变黄
g=255
r=255
h.putpixel((i,j), (r,g,b))
h.save("./ana_choice.png")
choice = pytesseract.image_to_string(Image.open("ana_choice.png"), lang='chi_sim') # 分析选项
choice = choice.replace(' ','')
#解决选项中有英文大写字母0的识别错误 if '0' in choice:
choice=choice.replace('0','O')
print (choice)
choices.append(choice)
return choices
def search_answer(question,choices):
ll = [0,10,20]
answer = []
for p in ll:
b = parse.quote(question.encode('gbk')) #转gbk码
url = 'https://zhidao.baidu.com/search?word=' + b + '&ie=gbk&site=-1&sites=0&date=0&pn=' + str(p) r = requests.get(url)
r.encoding = 'gbk' #网址转gbk编码
soup = BS(r.text, 'html.parser')
want = soup.find('div', id='wgt-list')
wants = want.find_all('dl', class_='dl')
for i in wants:
ans = i.find('dd', class_='dd answer').text
answer.append(ans)
choiceset = {}
choiceset['A'] = choices[0]
choiceset['B'] = choices[1]
choiceset['C'] = choices[2]
choiceset['D'] = choices[3]
for i in choiceset:
account = []
for j in answer:
if choiceset[i] in j:
account.append(j)
a = 0
for k in account:
a += 1
print('选' + i + '的可能性是' + str('%.2f' % (a * 100 / 30)) + '%')
def main(filename):
picsize = open_pic(filename)[0]
oldpic = open_pic(filename)[1]
firstpic = open_pic(filename)[2]
question = get_question(picsize,firstpic)
choices = get_choice(oldpic)
search_answer(question,choices)
if __name__ == '__main__':
start = datetime.datetime.now()
your = input('准备好了按y:')
if your == 'y':
os.system('adb shell screencap -p /sdcard/auto.png')
os.system('adb pull /sdcard/auto.png')
img = Image.open('auto.png')
img.convert('RGB')
img.save('auto.png')
main('auto.png')
end = datetime.datetime.now()
print ('本次一共花了'+str((end-start).seconds)+'秒')
尝试运行一下,发现运行时间太太太太长了,估计是图片识别会占用很长时间,每当我5个题目答完,第一题才刚刚分析出来,虽然过程中花了很多心思,但是这种效果肯定是没有实用性的,让人心酸。
2.Fiddler抓包
正打算放弃这个程序的时候,发现了Fiddler这个抓包工具,之前学爬虫的时候就听到过,但是那时候没认真研究。应用到这里刚刚好,通过Fiddler实时抓取头脑王者传输的数据,把数据保存下来给Python分析,接下来的事就简单得多了。
Fiddler手机抓包的教程网上有很多,重点是把传输的数据自动保存下来。使用Fiddler时最后设置成只看含有‘quiz’的url,不然会冒出很多无关的数据。
设置完之后玩一局游戏,软件中出现了五个新的数据,里面就包含了每一道题的信息。原来之前辛辛苦苦弄图片识别,现在这么容易就把题目和选项拿到手了。
接下来就是最重要的自动保存json数据,在软件中的‘FiddlerScript’--‘OnBeforeResponse’修改一下代码:
在原有的基础上加这段代码:
if(oSession.host == 'question.hortor.net'){
oSession.utilDecodeResponse(); //Decoding HTTP request in case it's gzip //Saving full request object (Including HTTP headers) oSession.SaveResponse('C:\\Users\\XXXX\\Desktop\\data\\response.txt',true);
//Saving just body oSession.SaveResponseBody('C:\\Users\\XXXX\\Desktop\\data\\responsebody.txt');
}
有了数据文件,接下来的事就交给Python了,直接贴代码:
import json
import time
from urllib import parse
import requests
from bs4 import BeautifulSoup as BS
def get_appinf(filename):
f = open(filename, 'r', encoding='utf-8')
try:
j = json.loads(f.read())
#判断数据文件是否有题目和选项 if 'quiz' in j['data'] and 'options' in j['data']:
num = j['data']['num']
quiz = j['data']['quiz']
print(('第'+str(num)+'题:'+quiz).center(50,'*')+'\n')
cho = j['data']['options']
else:
pass
return quiz,cho
except:
pass
f.close()
def search(question,choice):
pagenum = [0,10,20]
answer = []
for i in pagenum:
q = parse.quote(question.encode('gbk')) # 转gbk码
url = 'https://zhidao.baidu.com/search?word=' + q + '&ie=gbk&site=-1&sites=0&date=0&pn=' + str(i) requests.packages.urllib3.disable_warnings() # 忽视网页安全性问题
r = requests.get(url, verify=False) # 不验证证书
r.encoding = 'gbk' # 网址转gbk编码
soup = BS(r.text, 'html.parser')
want = soup.find('div', id='wgt-list')
wants = want.find_all('dl', class_='dl')
for i in wants:
ans = i.find('dd', class_='dd answer').text
answer.append(ans)
choiceset = {}
choiceset['A'] = choice[0]
choiceset['B'] = choice[1]
choiceset['C'] = choice[2]
choiceset['D'] = choice[3]
#计算四个选项在爬取百度答案中的出现次数 results = {}
for i in choiceset:
account = []
for j in answer:
if choiceset[i] in j:
account.append(j)
result = len(account)/30
results[i] = result
if i == 'D':
print(('选' + i + '的可能性是:%.2f%%' % (result * 100 )).center(50)+'\n')
else:
print(('选' + i + '的可能性是:%.2f%%' % (result * 100 )).center(50))
#选出数值最大元素的对应键 bestchoice = max(results.items(), key=lambda x: x[1])[0]
print (('此题最好选'+bestchoice).center(50,'-')+'\n\n\n')
def main():
try:
que,cho = get_appinf('C:/Users/XXXX/Desktop/data/responsebody.txt') #修改成你自己的保存位置
search(que,cho)
except:
pass
if __name__ == '__main__':
while True:
main()
time.sleep(2)
这次的程序实际效果比之前的好多了,在手机上的题目出来之前,Fiddler就能抓取到数据并通过Python找到答案,但是问题也是很明显,稍微复杂一点的题目百度也搜索不出来,还有反向题目(‘不属于’、‘不包括’‘不是’)的识别率也不高,偶尔也会被答题大神吊打,但是拿来娱乐一下其实也足够了,毕竟头脑王者不同什么登顶大会,答对题没有奖金。程序出来之后,花了大半个小时上了王者。
python识别文字答题_头脑王者的Python答题助手——从OCR文字识别到Fiddler抓包相关推荐
- fiddler使用_为什么要使用fiddler抓包?抓包用来干什么?
松勤软件测试 坚持教育初心 既问收获也问耕耘 这篇没有规整的文字叙述,是一些知识的杂谈记录~~~ 在我们做接口测试的时候,经常需要验证发送的消息是否正确,或者在出现问题的时候,查看手机客户端发送给se ...
- 全网最详细的Python+Requests接口测试教程:Fiddler抓包工具
本篇涵盖内容:fiddler.http协议.json.requests+unittest+报告.bs4.数据相关(mysql/oracle/logging)等内容. 文章是针对零基础入门接口测试和py ...
- python读取fiddler_大数据采集之python的docker爬虫技术-fiddler抓包软件详细配置(7)...
本篇文章探讨了大数据采集之python的docker爬虫技术-fiddler抓包软件详细配置(7),希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入. 挑选常用的功能给各位老铁介绍下 ...
- Python+Requests接口测试教程(1):Fiddler抓包工具
本书涵盖内容:fiddler.http协议.json.requests+unittest+报告.bs4.数据相关(mysql/oracle/logging)等内容. 刚买须知:本书是针对零基础入门接口 ...
- fiddler 自动响应数据保存_十分钟学IT:测试工程师得力助手Fiddler抓包之日常使用...
Fiddler是一款强大的抓包工具,通过改写HTTP代理,让数据经由Fiddler,借此来监控并截取到请求和返回数据.这样一来它不仅可以定位前后端问题,还能够记录客户端和服务端的所有http请求.设置 ...
- 命名实体识别 实体抽取_您的公司为什么要关心命名实体的识别
命名实体识别 实体抽取 Named entity recognition is the task of categorizing text into entities, such as people, ...
- 高考python必考题目_假如高考考python编程,这些题目你会几个呢?
Python(发音:英[?pa?θ?n],美[?pa?θɑ:n]),是一种面向对象.直译式电脑编程语言,也是一种功能强大的通用型语言,已经具有近二十年的发展历史,成熟且稳定.它包含了一组完善而且容易理 ...
- python入门第一课_入门第一课 Python入门涉及的问题及简单示例
很多初学者都在问:我想自学Python,该怎样入门?入门选择哪些书籍? 下面,我以自己的理解作出解答. 1.先说明大体的学习进度. Python确实入门较为容易,语法清晰易懂.一旦入了门再想提高就和其 ...
- python编码转换语句_好程序员Python教程之字符串编码知识小结
好程序员Python教程之字符串编码知识小结,提及Python字符串,你会想到什么?是ASCII,还是Unicode?他们之间是如何转换的?字符串编码和字符串有什么区别?接下来好程序员Python教程 ...
- 新手入门python的注意事项_【新手入门Python语言的方法】
2018年编程语言榜,Python位居榜首,很多学员对这门表示有着强烈的兴趣. 中公优教育小编这次就来谈谈Python入门方法. 下面直接进入今天的主题: 学编程,python算是一个不错的选择.因为 ...
最新文章
- python自动开发之(算法)第二十七天
- [J2SE 基础知识]2、抽象类和接口(上)
- 最懂中文的H5前端框架amazeUI
- 为什么在反向传播中感知器初始值不能为0_深度学习理论分享之——单层感知器简述...
- 2014年职称计算机word2003,2014年职称计算机考试Word2003模拟题及答案5
- JAVA设计模式之【单例模式】
- Android仿ios二级菜单侧滑,仿IOS的列表项滑动菜单——ListItemMenu
- [Swift]LeetCode19. 删除链表的倒数第N个节点 | Remove Nth Node From End of List
- java读取mysql配置文件_Linux运维:MySQL读写分离解决方案
- 四款机型全面开售 海蓝色iPhone 12 Pro最受欢迎
- 基于JAVA+SpringBoot+Mybatis+MYSQL的快递管理系统
- 考研数据结构--严版图相关代码 自用
- 汇编proto、proc、invoke伪指令与函数声明、函数定义、函数调用
- C++二叉树的 前中后序遍历(学C++必看必会)深度优先遍历详解
- MySql 使用关键字做字段名
- discuz template 模板文件说明
- 泱泱大中华,美丽我的家 - 俗晒网速,感受幸福
- 背景建模方法论文总结
- vivo计算机的隐藏功能介绍,vivo手机13个隐藏功能介绍,你知道几个?
- 如何安装VCC++6.0并创建第一个项目