由于自己的专业不是学计算机的,所以只能利用课余时间自学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抓包相关推荐

  1. fiddler使用_为什么要使用fiddler抓包?抓包用来干什么?

    松勤软件测试 坚持教育初心 既问收获也问耕耘 这篇没有规整的文字叙述,是一些知识的杂谈记录~~~ 在我们做接口测试的时候,经常需要验证发送的消息是否正确,或者在出现问题的时候,查看手机客户端发送给se ...

  2. 全网最详细的Python+Requests接口测试教程:Fiddler抓包工具

    本篇涵盖内容:fiddler.http协议.json.requests+unittest+报告.bs4.数据相关(mysql/oracle/logging)等内容. 文章是针对零基础入门接口测试和py ...

  3. python读取fiddler_大数据采集之python的docker爬虫技术-fiddler抓包软件详细配置(7)...

    本篇文章探讨了大数据采集之python的docker爬虫技术-fiddler抓包软件详细配置(7),希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入. 挑选常用的功能给各位老铁介绍下 ...

  4. Python+Requests接口测试教程(1):Fiddler抓包工具

    本书涵盖内容:fiddler.http协议.json.requests+unittest+报告.bs4.数据相关(mysql/oracle/logging)等内容. 刚买须知:本书是针对零基础入门接口 ...

  5. fiddler 自动响应数据保存_十分钟学IT:测试工程师得力助手Fiddler抓包之日常使用...

    Fiddler是一款强大的抓包工具,通过改写HTTP代理,让数据经由Fiddler,借此来监控并截取到请求和返回数据.这样一来它不仅可以定位前后端问题,还能够记录客户端和服务端的所有http请求.设置 ...

  6. 命名实体识别 实体抽取_您的公司为什么要关心命名实体的识别

    命名实体识别 实体抽取 Named entity recognition is the task of categorizing text into entities, such as people, ...

  7. 高考python必考题目_假如高考考python编程,这些题目你会几个呢?

    Python(发音:英[?pa?θ?n],美[?pa?θɑ:n]),是一种面向对象.直译式电脑编程语言,也是一种功能强大的通用型语言,已经具有近二十年的发展历史,成熟且稳定.它包含了一组完善而且容易理 ...

  8. python入门第一课_入门第一课 Python入门涉及的问题及简单示例

    很多初学者都在问:我想自学Python,该怎样入门?入门选择哪些书籍? 下面,我以自己的理解作出解答. 1.先说明大体的学习进度. Python确实入门较为容易,语法清晰易懂.一旦入了门再想提高就和其 ...

  9. python编码转换语句_好程序员Python教程之字符串编码知识小结

    好程序员Python教程之字符串编码知识小结,提及Python字符串,你会想到什么?是ASCII,还是Unicode?他们之间是如何转换的?字符串编码和字符串有什么区别?接下来好程序员Python教程 ...

  10. 新手入门python的注意事项_【新手入门Python语言的方法】

    2018年编程语言榜,Python位居榜首,很多学员对这门表示有着强烈的兴趣. 中公优教育小编这次就来谈谈Python入门方法. 下面直接进入今天的主题: 学编程,python算是一个不错的选择.因为 ...

最新文章

  1. python自动开发之(算法)第二十七天
  2. [J2SE 基础知识]2、抽象类和接口(上)
  3. 最懂中文的H5前端框架amazeUI
  4. 为什么在反向传播中感知器初始值不能为0_深度学习理论分享之——单层感知器简述...
  5. 2014年职称计算机word2003,2014年职称计算机考试Word2003模拟题及答案5
  6. JAVA设计模式之【单例模式】
  7. Android仿ios二级菜单侧滑,仿IOS的列表项滑动菜单——ListItemMenu
  8. [Swift]LeetCode19. 删除链表的倒数第N个节点 | Remove Nth Node From End of List
  9. java读取mysql配置文件_Linux运维:MySQL读写分离解决方案
  10. 四款机型全面开售 海蓝色iPhone 12 Pro最受欢迎
  11. 基于JAVA+SpringBoot+Mybatis+MYSQL的快递管理系统
  12. 考研数据结构--严版图相关代码 自用
  13. 汇编proto、proc、invoke伪指令与函数声明、函数定义、函数调用
  14. C++二叉树的 前中后序遍历(学C++必看必会)深度优先遍历详解
  15. MySql 使用关键字做字段名
  16. discuz template 模板文件说明
  17. 泱泱大中华,美丽我的家 - 俗晒网速,感受幸福
  18. 背景建模方法论文总结
  19. vivo计算机的隐藏功能介绍,vivo手机13个隐藏功能介绍,你知道几个?
  20. 如何安装VCC++6.0并创建第一个项目

热门文章

  1. 2022,云上开发的新纪元
  2. Eclipse安装插件详解
  3. C++Builder实现鼠标钩子
  4. 物联网——无线通信技术
  5. 如何制作统计报表(盈帆报表: efreprt.com)
  6. 如何直接打开AutoCAD格式的DXF文件
  7. 关于未知的USB设备(设备描述符请求失败)的解决方法。
  8. 02-即时通讯-XMPP 简单介绍
  9. 基于jsp与基于java有什么区别_JSP和HTML之间有什么区别
  10. 介绍下JS里4种实现页面跳转的方法