我用Python开发了一个搜题神器

Python编程与实战

共 6579字,需浏览 14分钟

 ·

2021-04-14 09:20


专业搜题,家长好帮手

很早之前曾经做过一个图片识别的项目,当时有一项功能是整题识别,即传入数学题的截图,可通过ocr技术识别出图片内容,但当时只限于识别文字,并未作更深一步的处理

现在想来实用性并不强,毕竟大家更需要的是解题思路,而不是让AI读出题干(题干的文字,我都认识,连起来我就不知道怎么下手去做了 = = ),

最近刚好有时间,于是尝试来为有娃的朋友做一个搜题神器。

鉴于之前整题识别的开发使用有道智云的良好体验,我再次打开其官方文档,果然找到了拍照搜题服务的开放API

轻车熟路地做了一个简单的批量搜题demo, 下面分享一下开发过程。

调用API接口的准备工作

首先,是需要在有道智云的个人页面上创建实例、创建应用、绑定应用和实例,获取到应用的id和密钥。具体个人注册的过程和应用创建过程详见文章

开发过程详细介绍

下面介绍具体的代码开发过程。

API接收的参数较为简单:

签名sign生成方法如下:
signType=v2;
sign=sha256(应用ID+input+salt+curtime+应用密钥)。
其中,input的计算方式为:input=q前10个字符 + q长度 + q后10个字符(当q长度大于20)或 input=q字符串(当q长度小于等于20)。

需要注意的是,API对题目图片有如下要求:

Demo开发:

这个demo使用python3开发,包括maindow.py,QuestionClass.py,OcrQuestion.py 三个文件,分别为demo的界面、界面逻辑处理和ocr搜题方法的封装。

1. 界面部分:

UI 部分较简单,主要功能为选择待题目图片、选择批改结果存储路径。其布局代码如下:

root=tk.Tk()root.title(" youdao ocr question test")frm = tk.Frame(root)frm.grid(padx='50', pady='50')
# 选题和结果保存按钮btn_get_file = tk.Button(frm, text='选择题目图片', command=get_files)btn_get_file.grid(row=0, column=0, ipadx='3', ipady='3', padx='10', pady='20')text1 = tk.Text(frm, width='40', height='10')text1.grid(row=0, column=1)btn_get_result_path=tk.Button(frm,text='选择搜索结果路径',command=set_result_path)btn_get_result_path.grid(row=1,column=0)text2=tk.Text(frm,width='40', height='2')text2.grid(row=1,column=1)

# 搜题按钮btn_sure=tk.Button(frm,text="搜题",command=search_question_files)btn_sure.grid(row=4,column=1)
root.mainloop()

其中启动按钮btn_sure的绑定事件search_question_files()来根据题目照片搜题,并在完成后打开结果存储路径:

def search_question_files():    question.start_ocr()    os.system('start '+question.result_path)
2. QuestionClass.py

这里主要配合UI的逻辑,调用搜题方法。

首先定义一个类Question:

class Question():    def __init__(self,file_paths,result_path):          self.file_paths=file_paths    # 题目照片存储路径        self.result_path=result_path  # 结果路径

start_ocr()方法调用connect()方法依次搜题并保存结果。

def start_ocr(self):    for file_path in self.file_paths:        result=connect(file_path)        print(file_path)       self.save_result_format(file_path,result)

从OcrQuestion.py的connect方法获取的结果是json格式,save_result_format()方法,解析从接口取得的接口,格式整理,保存结果到html:

    def save_result_format(self,file_path,result):        result_file_name=os.path.basename(file_path).split('.')[0]+'_result.html'        f=open(self.result_path+'/'+result_file_name,'w',encoding='utf-8')        result_json= json.loads(result)        if result_json['errorCode'] == '0':            data=result_json['data']            questions=data["questions"]            text=data["text"]            f.write("题目识别:<br/>"+text)            i=0            for answers in questions:                i=i+1                subject="科目:"+answers["subject"]+"<br>"                answer="答案:" +answers["answer"]+"<br>"                analysis="分析:"+answers["analysis"]+"<br>"                knowledge="知识点:"+answers["knowledge"]+"<br>"                print(subject+answer+analysis+knowledge)                result_each="<h3>搜题结果"+str(i)+"<br></h3>"                result_each=result_each+subject+answer+analysis+knowledge+"<br>=================这是一条分隔符============<br>"                f.write(result_each)        else:            f.write("result error code:"+result_json['errorCode'])
3. OcrQuestion.py

OcrQuestion.py 中封装请求ocr搜题API的方法,其中最主要的方法是connect():

def connect(pic_path):    f = open(pic_path, 'rb')  # 二进制方式打开图文件    q = base64.b64encode(f.read()).decode('utf-8')  # 读取文件内容,转换为base64编码    f.close()
data = {} data['q'] = q data['signType'] = 'v2' curtime = str(int(time.time())) data['curtime'] = curtime salt = str(uuid.uuid1()) signStr = APP_KEY + truncate(q) + salt + curtime + APP_SECRET sign = encrypt(signStr) data['appKey'] = APP_KEY data['salt'] = salt data['sign'] = sign
response = do_request(data) result=response.content.decode('utf-8') print(result)    return result

API响应结果示例

{    "data":{        "questions":[            {                "score":0.9875,                "answer":"D",                "subject":"历史",                "id":"a9db8f1252778836c99204e5cf9d7738",                "analysis":"",                "type":"",                "content":"学者们认为,五四运动标志着中国民族意识极大觉醒,表现在<br />A.近代民族民主思想开始传播 B .揭开了反帝反封建斗争的序幕<br />C.开启了近代中国的思想启蒙 D .各阶层民众的广泛动员和参与",                "knowledge":""            },            {                "score":0.9875,                "answer":"D <br>注意题干“中国民族意识极大觉醒”,结合所学可知,在五四运动过程中,学生、工人、商人都投入到之中,即各阶层民众的广泛动员和参与,符合题意,故D项正确. <br>在戊戌变法前后,中国民族民主思想就已经开始传播,故A项错误. <br>五四运动是一次反帝反封的爱国运动,但不是反帝反封斗争的开始,在这时期还没有明确提出反帝反封的革命纲领,故B项错误. <br>中国近代是在新文化运动期间传播民主思想,进行了思想的启蒙,故C项错误. <br>故选D.",                "subject":"历史",                "id":"2f8b9c814f064131cc7b2bead54f15da",                "analysis":"本题考查五四运动.考查五四运动的意义.考查学生对基础知识的识记、运用能力.",                "type":"选择题",                "content":"学者们认为,五四运动标志着中国民族意识极大觉醒,表现在(  ) <p class="question_option">A.近代民族民主思想开始传播<br/>B.揭开了反帝反封建斗争的序幕<br/>C.开启了近代中国的思想启蒙<br/>D.各阶层民众的广泛动员和参与 </p>",                "knowledge":"/人类政治文明发展史/近代中国反侵略、求民主的潮流/五四运动"            },            {                "score":0.9875,                "answer":"D <br>【答案】 <p>D</p> <p></p>",                "subject":"历史",                "id":"48a28969d882f20b04ffec15c8f1b94c",                "analysis":"<p>题目问的五四运动,在戊戌变法前后,中国民族民主思想就已经开始传播,所以A不正确。五四运动是一次反帝反封的爱国运动,但不是反帝反封斗争的开始,在这时期还没有明确提出反帝反封的革命纲领,所以B不正确。中国近代是在新文化运动期间传播民主思想,进行了思想的启蒙,所以C不正确。在五四运动 过程中,学生、工人、商人都投入到之中,所以D正确。</p> <p> </p>",                "type":"选择题",                "content":"<p>学者们认为,五四运动标志着中国民族意识极大觉醒,表现在</p> <p></p> <p class="question_option">A.近代民族民主思想开始传播<br/>B.揭开了反帝反封建斗争的序幕<br/>C.开启了近代中国的思想启蒙<br/>D.各阶层民众的广泛动员和参与 </p>",                "knowledge":"/人类政治文明发展史/近代中国反侵略、求民主的潮流/中国共产党第一次全国代表大会"            }        ],        "text":"学者们认为,五四运动标志着中国民族意识极大觉醒,表现在 A,近代民族民主思想开始传播B揭开了反帝反封建斗争的序幕 C,开启了近代中国的思想启蒙D。各阶层民众的广泛动员和参与"    },    "errorCode":"0"}

响应结果是以json形式输出,包含字段如下表所示:

效果展示

demo操作演示

来看看结果吧:

数学题搜索结果展示:

历史题搜题结果


总结

有道智云的整体搜索API文档清晰,题目范围极广而且可以自动判断学科,搜索结果可谓“举一反三”,会返回几个可能的相近题目,很具有参考价值,值得推荐!数学解答题会返回相关图片、公式等,用在web项目中效果灰常不错。

项目地址:https://github.com/LemonQH/OcrQuestion


PS:如果觉得我的分享不错,欢迎大家随手点赞、在看。



笑死,小米新logo是这么来的


15 个让新手爱不释手的 Python 高级库


2021 年 Python 程序员必备的 VS code 插件!


浏览 15
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报