验证码识别成为了对抗反爬虫的必修课之一,看了崔庆才著的《python3网络爬虫开发实战》后受益匪浅,本专题将着重学习记录不同的验证码识别方式:图像验证码、宫格验证码、极验滑动验证码、点触验证码。
s
点触验证码识别
先看看效果:
下图为12306的点触验证码,识别难点有两个:
文字识别,即首先要识别出“盘子”二字,但往往该文字经过了一系列的变换,如果借助第一节提到的OCR技术,基本上无法识别。
将图片转化为相应的文字。
另一种验证码:
( 和上述验证码相比较而言,会简单一些,但是识别思路相同,本文就着重记录一下第一种验证码的识别过程。)
识别思路
点触验证码难度较大,我们可以接触互联网上一些验证码服务平台,他们提供7×24小时的服务,并且识别准确率在90%以上。
大致流程是将验证码图片按照字节流的形式传递给服务平台,平台几秒钟后将会返回一个带有坐标信息的字段,该坐标信息就是我们需要点击的位置。按照得到的坐标信息进行点击,便可以完成识别。
验证码服务平台往往提供了多种类型的验证码识别,例如“超级鹰”网址:https://www.chaojiying.com/,其提供了数字、中英文、特殊字符、数学计算和坐标选择识别等多种验证码类型的识别。点触验证码识别就是坐标选择识别的一种。下面将利用该平台进行识别。
详细过程及代码
获取超级鹰python API
1 | import requests |
代码如上,其定义了一个Chaojiying_Client的类,内有三个参数,分别是超级鹰的用户名、密码、软件ID。内含两个函数 PostPic()、ReportError()。
PostPic()需要传入图片对象和验证码的代号(验证码类型)。该方法会将图片对象发送给给超级鹰的后台进行识别,然后返回一个JSON。
ReportError()发生错误时的回调。
验证过程
初始化、登录
1 | import time |
获取验证码图片
该截图操作在各类验证码识别中会经常使用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
27def get_element(self):
'''获取验证图片对象'''
element = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'loginImg')))
return element
def get_position(self):
'''获取验证码位置'''
element = self.get_element()
time.sleep(2)
location = element.location
size = element.size
top,bottom,left,right = location['y'],location['y']+size['height'],location['x'],location['x']+size['width']
return (top,bottom,left,right)
def get_screenshot(self):
'''获取网页截图'''
screenshot = self.browser.get_screenshot_as_png()
screenshot = Image.open(BytesIO(screenshot))
return screenshot
def get_image(self,name='captcha.png'):
'''获取验证码图片'''
top,bottom,left,right = self.get_position()
print('验证码位置',top,bottom,left,right)
screenshot = self.get_screenshot()
captcha = screenshot.crop((left,top,right,bottom))
return captcha
解析识别信息
1 | def get_points(self, captcha_result): |
平台返回的JSON格式信息如下:1
2
3
4
5
6
7{
'err_no': 0,
'err_str': 'OK',
'pic_id': '8056217061965800013',
'pic_str': '29,72|257,71',
'md5': '8de76ac4036ebab2b1e05375c1bf84b8'
}
get_points()方法即是将’pic_str’中的坐标信息格式化为:[29, 72] [257, 71]
点击验证图片
1 | def touch_click_words(self,locations): |
其中move_to_element_with_offset函数的参数及解释:
点击登录
1 | def login(self): |
控制流程
首先打开12306网站,并刷新验证码(button),然后将验证码图片对象按照字节流的格式传递给超级鹰平台,并将返回的locations信息传递给touch_click_words()函数,最后完成验证码识别。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 def crack(self):
'''入口'''
self.open()
button = self.refresh_code()
button.click()
image = self.get_image()
bytes_array = BytesIO()
image.save(bytes_array,format='PNG')
#识别验证码
result = self.chaojiying.PostPic(bytes_array.getvalue(),CHAOJIYING_KIND)
print(result)
locations = self.get_points(result)
self.touch_click_words(locations)
self.login()
if __name__ == "__main__":
crack = Crackclick()
crack.crack()
关键字总结
- 获取图片位置、截取图片
- 调用超级鹰API
- ActionChains
- 字节流处理