avatar

Catalog
如何用Python写一个OCR小工具接口

概述

后PC时代,前后端分离成为一种潮流,一套API多处使用节省了很多劳动。Instance APP慢慢进入我们的时代,前台的重要性变得更大起来。是时候学一学VUE了。后台的工作从原来的填充数据跳转页面变成了被前台主动拉取数据。RESTful API渐渐成为后台主要的开发任务。对于小程序等等使用Springboot等的Java程序显得非常”重“。脚本语言作为一种轻量化的语言开发这些API的时候游刃有余,性能也不是问题。

Django是Python的一个Web框架,功能丰富适合喜欢“偷懒”的人使用,你可以从下面发现,其实真正的代码没几行。甚至比html的代码都少不得不说Python用来开发API太有优势了。互联网上百分之八十的网站都是用脚本语言(PHP)开发的,Python来进行web开发完全没有问题,知乎的后台就是Python。

详细过程

框架的选择

Framework Detail
Django 全能型Web框架
web.py: 一个小巧的Web框架
Flask: 和Bottle类似的Web框架
Bottle: 和Flask类似的Web框架
Tornado: Facebook的开源异步Web框架。

知乎使用的框架是Tornado。本文采用Django框架,在于其“全能”。当然这也带来了一个问题,相较其他而言其设计模式固定不够灵活。好处是模块比较多,有成熟的设计模式,省力✌️。Flask则比较精简灵活,总体而言也是不错的选择,以后可以尝试。

virtualenv安装

Python 开发中也会用到各种包,如果每次都是全局安装的话不仅磁盘承受不了,恐怕各种包之间也会产生冲突。

因此安装虚拟工具,可以把python本体和他的包们都置于这个环境中,各个项目互不打扰。

首先,我们用pip安装virtualenv。然后创建一个独立的Python运行环境,命名为venv。

shell
1
2
3
4
$ pip3 install virtualenv
$ mkdir my_project
$ cd my_project
$ virtualenv --no-site-packages venv

命令virtualenv就可以创建一个独立的Python运行环境,我们还加上了参数–no-site-packages,这样,已经安装到系统Python环境中的所有第三方包都不会复制过来

新建的Python环境被放到当前目录下的venv目录。有了venv这个Python环境,可以用source进入该环境:

shell
1
$ source venv/bin/activate

虚拟环境

注意到命令提示符变了,有个(venv)前缀,表示当前环境是一个名为venv的Python环境。

如果前面出现了venv,则表面虚拟环境激活成功。虚拟环境激活成功,虚拟环境所在解释器就会添加到PATH中。虚拟环境激活后,我们就可以安装项目所需的包。

项目完成了,虚拟环境不想用了,想退出怎么办呢??方法很简单,只需输入deactivate,就会退出当前虚拟环境。

退出))

其他可能会用到的命令

关于venv))

导入用到的python库

用到的库放在了txt文档中使用pip命令导入

shell
1
$ pip3 install -r requirements.txt

requirements.txt的内容如下

Code
1
2
3
4
gevent>=1.2.2,<2.0.0
django>=1.11.0,<2.0.0
typing
baidu-aip

关于Python面向对象

在Python中可以使用class关键字定义类,类的函数的第一个参数必须是self。

python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class FileUpload(View):
def get(self, request):

return render(request, 'uploadimg.html',{'title':'OCR 图片转文字'})


def post(self, request):

obj = request.FILES.get('uploadimg')
img=ImgTool(obj.read())
text=img.do_the_job()

ret={'status':True,'result':text}

return HttpResponse(json.dumps(ret))

括号中是父类,代表一种继承关系,在Python中是支持多重继承的,也就是我们可以为一个类同时指定多个父类。可以在类名的()后边添加多个类,来实现多重继承。多重继承,会使子类同时拥有两个父类。

python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class ImgTool(object):

def __init__(self,file_content):
self.file_content=file_content

def do_the_job(self):

image = self.file_content

""" 调用通用文字识别, 图片参数为本地图片 """
res = client.basicGeneral(image)
text = ''
words = res['words_result']
for word in words:
text = text + word['words']+"\n"
print(text)
return text

顺便推荐一下Pylint

Pylint 是一个 Python 代码分析工具,它分析 Python 代码中的错误,查找不符合代码风格标准(Pylint 默认使用的代码风格是 PEP 8,具体信息,请参阅参考资料)和有潜在问题的代码。

Django的简单说明

可以使用命令,创建Django项目。

shell
1
$ django-admin.py startproject djangoDemo

新建的项目中会自动生成目录和几个文件

说明:
settings.py: 管理项目的配置信息
urls.py: 声明请求url的映射关系
wsgi.py: python程序和web服务器的通信协议
manage.py: 一个命令行工具,用来和Django项目进行交互,如运行项目、添加管理员等。

另外Django对数据库也提供了很好的支持。

Django 对 REST 化都有相应的包。其实用它来做这个小的项目有点“杀鸡用牛刀”的感觉。

如何实现上传文件进度条

进度条在对于用户体验来说是非常重要的,每个人都希望自己的动作得到响应。如果不能得到即时反馈,会变得焦虑起来。众所周知,进度条就是“两个div”通过内层宽度样式的变化产生进度条增长的效果。这里也是这么实现的。具体代码如下:

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$.ajax({
url:'/upload/', // 这里对应url.py中的 url(r'upload', views.upload)
type:'POST',
data: form_data,
processData: false, // tell jquery not to process the data
contentType: false, // tell jquery not to set contentType
xhr:function(){
myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){ // check if upload property exists
myXhr.upload.addEventListener('progress',function(e){
var loaded = e.loaded;//已经上传大小情况
var tot = e.total;//附件总大小
var per = Math.floor(100*loaded/tot); //已经上传的百分比
$("#progress").html( per +"%" );
$("#progress").css("width" , per +"%");
console.log('附件总大小 = ' + loaded);
console.log('已经上传大小 = ' + tot);
if(per=='100'){
$("#progress").html("正在解析...");
}
}, false); // for handling the progress of the upload
}
return myXhr;
},
success: function(data) {


$('#test1').html(JSON.parse(data).result)
$('textarea[autoHeight]').autoHeight();
$("#progress").html("");
$("#progress").css("width","0px")
//alert('success');
}
});

运行与发布

Django 运行还是快速而又方便的,可以通过前面提到的manage.py脚本来运行程序。

python
1
$ python manage.py runserver

当然生产环境和开发环境是不同的,测试时用的是Django内建的WSGI Server,生产服务则是nginx+uwsgi等。这样可以提供对高并发的支持。具体来说这个OCR API选择的是openresty。但这是“被动选择的”。

关于云引擎

小程序时代,api的提供变得更为重要,云引擎也是在这个理念下出现的产品,其目的就是为前台小程序提供一个api。

提供了数据库服务等等,甚至程序崩溃了还能自动重新部署。

相比vps来说,具有一个完善的后端服务,使用它提供的cli工具部署起来非常方便,每次部署还只会更新改动的部分。

另外,本博客也利用它开通了评论系统。

总结

Python以简单著称,和PHP同属于脚本语言。感觉似乎脚本语言这种解释性的要比编译型的速度慢。但从实际效果来看还不是这样。因为像Java测试时每次都要运行Tomcat要等好一会。而Python的WSGI server跑起来速度比Tomcat快多了。(当然Java Web是可以热更新的,这样就不用每次重启了)

Python Web与传统的Java Web的开发相比要简单不少,Java中每一行代码都要先考虑其对象的类型,这里不存在这个麻烦。有关于文件的读取只用了几行代码。这也是脚本语言的优势,难怪PHP的这么流行,LNMP都成了环境搭建的必选项。

移动互联网和物联网的时代,服务器的性能不再是开发的瓶颈,效率才是。快速迭代才能适应当前的快节奏。以前微软系统发布以后只会更新安全补丁,而应用程序大部分不更新,即便更新了也是很少人会关心。现在则进入了快节奏,像miui每周一个开发版、各种APP每隔一段时间就会更新功能;而且节日也会发版,更别提还有Web热更新这种东西。有新闻说苹果正在开发一一个名为“Clips”的新API,将App的部分功能剪辑出来,以链接或者二维码的形式传播出去,是不是有点类似微信小程序的感觉。互联网本身是去中心化的每个人都可以是客户端和服务器。但是今天互联网的割裂感越来越大,PC时代在应用程序的大开发以后人们都纷纷使用Web服务,比如最开始人们是用暴风影音、QQ影音这些桌面端程序的,后来转移到Web的视频网站。而后PC时代,小程序这种Web的产物却是更加割裂了。它不能够被搜索引擎索引,也不让人们使用超链接跳出各个服务商制造的壁垒。说明移动互联的时代搜索引擎不太行了。不知道苹果谷歌们怎么解决这个问题。

随着Instant app走入舞台。Web开发也要去适应它,快速的迭代,积极的开发接口。脚本语言无疑是最好的。相比于Php,Python的优势还在于他在AI和大数据方面的应用,尽管其他语言通过胶水语言(即python lua等)来作为黏合剂也可以调用这些服务,但是多个翻译总不如直接对话。

就OCR识别来说,测试了几个网站,识别率总不尽人意。可以看出传统的图片转文字的方法存在着缺陷:只是机械的解析没有考虑语言的关联性。缺少重要的线索使识别变得机械了。通过样本训练起来的百度AI,识别率就要高不少。这也是AI给传统技术带来的变化。

So,人生苦短,我用Python。

参考

python虚拟环境 | virtualenv 的简单使用 (图文) https://www.cnblogs.com/qiutenglong/p/10442479.html

Python - 100天从新手到大师
https://github.com/jackfrued/Python-100-Days

Pylint 是什么
https://www.ibm.com/developerworks/cn/linux/l-cn-pylint/index.html

Author: Winter X
Link: https://xdeam.github.io/2020/04/17/pyweb/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

Comment
1