开发软件系统时必然会有用户登陆的模块。每次验证自己的功能时,总是绕不开输入账号密码,这已经是很麻烦的了,还得输入不好辨认的验证码。
为了简化登陆步骤,我通过使用图像识别 OCR 技术,和Web应用框架Flask搭建一个验证码自动识别的服务。并结合强大的浏览器插件Tampermonkey,编写一个简单的油猴脚本,在不入侵源系统的基础上,实现不输入验证码登陆。也为后期自动化测试奠定可操作的基础。
示例环境Centos8
sudo yum install epel-release
sudo yum install tesseract-devel leptonica-devel
yum install -y libjpeg-devel libpng-devel
yum install -y autoconf automake libtool
yum install -y git wget
yum install -y gcc gcc-c++
yum install -y tesseract tesseract-devel
yum install -y python36
创建python虚拟环境
python3.6 -m venv py36env
source py36env/bin/activate
python依赖安装
pip install flask
pip install flask_cors
pip install tesserocr
pip install pillow
pip install uwsgi
找不到tesseract包
yum list tesseract
无数据
解决
yum -y install yum-utils
yum-config-manager --add-repo https://download.opensuse.org/repositories/home:/Alexander_Pozdnyakov/CentOS_8/
TESSDATA_PREFIX问题
[Sajor@10-7-151-243 AutoLogin]$ tesseract captcha_denoising.png result
Error opening data file /usr/share/tesseract/4/tessdata/eng.traineddata
Please make sure the TESSDATA_PREFIX environment variable is set to your "tessdata" directory.
Failed loading language 'eng'
Tesseract couldn't load any languages!
Could not initialize tesseract.
解决
搜索tessdata文件夹
find / -type d -iname "tessdata"
发现确实没有 eng.traineddata
文件,则下载一个。
wget https://github.com/tesseract-ocr/tessdata/raw/master/eng.traineddata
sudo mv -v eng.traineddata /usr/local/share/tessdata/
我们开发的系统登陆页面是这样的
先分析此验证码图片有以下特点
我们可以这样处理
针对颜色多样,我们可以先给图片做灰度处理再做二值化处理,这是识别前处理验证码的基操。
灰度图像: 每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。
转换公式:L = R * 299/1000 + G * 587/1000+ B * 114/1000
from PIL import Image
image = Image.open(file).convert('L')
之后对灰度图片做二值化,使图片非黑即白,可以通过调整下图中threshold
的值来过滤少部分颜色浅的干扰线,因为图片中字母部分也可能出现亮黄色的情况,为了防止误删要识别的文字,我将阈值先调高一些,少过滤一些颜色。
二值图像: 非黑即白。每个像素用8个bit表示,0表示黑,255表示白。
image.convert('1')
因为字母较大,像素较多,而干扰线的较细,我们可以使用这个策略来去除干扰线。
遍历图片中每一个像素点:
如果这个像素点为黑色:
观察它四面八方的像素点颜色,如果少于四个点为黑色:
将这个点变为白色
这个策略的大致意思就是将图像中置于边缘的像素删除掉。因为字母较大,像素比较多,删除一圈也不会有什么影响。
通过上一步的降噪处理得到的结果已经很好了,因为线条笔直没有扭曲,可以直接丢给OCR来识别了!
网络中现成的OCR识别工具有很多,比如百度OCR,Tesseract-OCR。
第三方的OCR得经过注册,使用他们提供的token调用接口,我就直接使用Python的第三方库Tesseract来搞。
安装必要的包之后直接调用即可。
import tesserocr
result = tesserocr.image_to_text(image)
使用Jupyter notebook 验证好功能后,将代码封装成类,方便调用。
之后使用Flask的 helloworld 工程简单修改一下,实现一个可调用的接口。
简单实用uwsgi
部署一下这个web项目,配置uwsgi.ini
文件将下文中/root/AutoLogin
路径改为自己的目录。
[uwsgi]
master = true
http=:5000
chdir = /root/AutoLogin
wsgi-file=/root/AutoLogin/app.py
callable=app
processes=4
threads=2
buffer-size = 65536
vacuum=true
pidfile =/root/AutoLogin/uwsgi.pid
启动命令:uwsgi --ini uwsgi.ini
重启命令:uwsgi --reload uwsgi.pid
关闭命令:uwsgi --stop uwsgi.pid
jquery修改input的值,vue获取不到的解决办法
$("input[name='aa']").val(2333)
//触发一下该input的input事件
$("input[name='aa']")[0].dispatchEvent(new Event('input'))
新建一个配置文件
vi /etc/nginx/conf.d/autologin.conf
输入以下内容
server{
listen 80;
listen [::]:80;
server_name autoLogin.sajor.top;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location /{
proxy_pass http://localhost:5000;
}
}
检查并重启
nginx -t
service nginx restart
查看 mem top 10
ps aux | grep -v PID | sort -rn -k 4| head
GitHub
# 1.0为tesseract版,最新代码已更换新ocr库
git clone -b 1.0 https://github.com/565785929/AutoLogin
之后升级为 dddd_ocr 库,安装比tesseract方便很多。
# 若报错需安装 mesa-libGL.x86_64
> ImportError: libGL.so.1: cannot open shared object file: No such file or directory
yum install mesa-libGL.x86_64
vue框架有双向绑定机制,在写页面插件的时候,只调用输入框的value属性并不能修改变量的值。需要调用一下 .dispatchEvent(new Event("input"));
触发事件。
document.getElementsByTagName("textarea")[0].value = "123";
document.getElementsByTagName("textarea")[0].dispatchEvent(new Event("input"));
-- 未完待续。