安装
首先安装 Tesseract-OCR,在 Mac 端可直接使用 Homebrew 进行安装
brew install tesseract
然后是 pytesseract,这是对 Tesseract 的封装,可直接在 Python 中调用。
pip install pytesseract
和用于图片处理的 PIL
pip install pillow
以及用于发送 HTTP 请求的 requests
pip install requests
代码实现
用 Chrome 打开教务系统首页,登录页面如图
首先的问题是如何获取验证码。
打开开发者工具切换到 Network 标签下,点击“看不清,换一张”刷新验证码,获取到如下请求
其只有一个参数为随机生成的 0-1 之间的浮点数。
captcha_url = 'http://urp.xxxx.cn/validateCodeAction.do'
captcha_data = {
'random': random.random()
}
response = session.get(captcha_url, params=captcha_data)
file = open('captcha.png', 'wb')
file.write(response.content)
file.close()
获取一张验证码保存至本地,验证码类似于此
但是由于背景的干扰,直接对此图片进行识别成功率很低,所以还需要对它进行处理。
打开刚才保存的图片,由于图片太小影响识别,首先将其放大两倍。
im = Image.open('captcha.png')
w, h = im.size
im = im.resize((w*2, h*2))
然后进行灰度处理。
gray = im.convert('L')
接下来是最重要的一步操作 —— 二值化
简单地来说,就是将灰度图像大于某个临界灰度值的像素灰度设为灰度极大值,把小于这个值的像素灰度设为灰度极小值,从而呈现出明显的黑白效果。
threshold = 150
able = []
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
out = gray.point(table, '1')
out.save('captcha_thresholded.png')
处理之后的效果如图
对比原图可以说清晰了不少,此时就可以较为精确地识别内容了。
由于依然不能保证 100% 的识别准确度,我还对识别结果进行了一些处理。
首先去除结果字符串中除字母和数字外的其它字符,然后验证结果是否为四位长度。如果长度不对,就刷新获取新的验证码进行识别。
最终的识别函数如下:
def get_captcha(session):
for i in range(10):
captcha_url = 'http://urp.xxxx.cn/validateCodeAction.do'
captcha_data = {
'random': random.random()
}
response = session.get(captcha_url, params=captcha_data)
file = open('captcha.png', 'wb')
file.write(response.content)
file.close()
im = Image.open('captcha.png')
w, h = im.size
im = im.resize((w*2, h*2))
gray = im.convert('L') # 灰度处理
threshold = 150
table = []
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
out = gray.point(table, '1')
out.save('captcha_thresholded.png')
th = Image.open('captcha_thresholded.png')
code = pytesseract.image_to_string(th)
code = filter(str.isalnum, code)
code = ''.join(list(code))
if len(code) == 4:
break
return code
获取到验证码,就可以进行登录了。
在账号、密码和验证码栏随便填写一些信息并点击登录,在所有请求中找到这一条为登录请求
点开详细信息划到最下面,得到登录信息的表单结构,其中 zjh
为账号,mm
为密码,v_yzm
为验证码,其它项为空可忽略(先把命名的拖出去枪毙 5 分钟,这都什么鬼名字)。
仿照此结构构造登录表单
post_data = {
'zjh': username,
'mm': password,
'v_yzm': captcha
}
发送登录请求
session.post(login_url, data=post_data)
最后,我们可以通过登录成功页面中的地址来判断是否登录成功,如果登录成功 ststus_code 即为 200。
outline_url = 'http://urp.xxxx.cn/outlineAction.do'
response = session.get(outline_url)
if(response.status_code == 200):
print('success')
else:
print('false')