超级鹰
在这个项目中使用超级鹰来识别验证码。超级鹰的官方接入文档如下。
1 #!/usr/bin/env python 2 # coding:utf-8 3 4 import requests 5 from hashlib import md5 6 7 class Chaojiying_Client(object): 8 def __init__(self, username, password, soft_id): 9 self.username = username 10 password = password.encode('utf8') 11 self.password = md5(password).hexdigest() 12 self.soft_id = soft_id 13 self.base_params = { 14 'user': self.username, 15 'pass2': self.password, 16 'softid': self.soft_id, 17 } 18 self.headers = { 19 'Connection': 'Keep-Alive', 20 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', 21 } 22 def PostPic(self, im, codetype): 23 """ 24 im: 图片字节 25 codetype: 题目类型 参考 http://www.chaojiying.com/price.html 26 """ 27 params = { 28 'codetype': codetype, 29 } 30 params.update(self.base_params) 31 files = {'userfile': ('ccc.jpg', im)} 32 r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers) 33 return r.json() 34 def ReportError(self, im_id): 35 """ 36 im_id:报错题目的图片ID 37 """ 38 params = { 39 'id': im_id, 40 } 41 params.update(self.base_params) 42 r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers) 43 return r.json() 44 45 if __name__ == '__main__': 46 chaojiying = Chaojiying_Client('超级鹰用户名', '超级鹰用户名的密码', '软件ID') # 用户中心 > 软件ID 生成一个用来接入接口的软件ID 47 im = open('验证码.jpg', 'rb').read() # 如果是WIN系统,有时本地图片路径可能须要双斜杠// 48 print(chaojiying.PostPic(im, 1902)) # 1902是需要验证码的类型,为常见4~6位英文数字。可以在官网查看更多类型。
思路
1 使用webdriver调用谷歌浏览器,然后请求滴滴打码网站。
2 通过selenium的xpath定位方法找到输入账号、密码、验证码、登陆的位置,并且传送具体的账号、密码给对应的位置。
3 对于传送验证码的问题:首先需要重新单独请求验证码,然后将验证码下载到本地,接着使用超级鹰来识别下载到本地的验证码,把识别后的验证码传送到网页中输入验证码的位置。
4 点击登陆的位置。
1 from selenium import webdriver 2 import request 3 4 #打开谷歌浏览器 5 driver = webdriver.Chrome(r'D:Python37Libchromedriver.exe') 6 #第一次请求滴滴打码网站 7 driver.get('http://www.ddocr.com/user/login.html')
8 #传送账号、密码到相应的位置 9 driver.find_element_by_xpath('//*[@id="account"]').send_keys('账号') 10 driver.find_element_by_xpath('//*[@id="password"]').send_keys('密码') 11 12 #第二次重新请求下载到本地的验证码 13 src = driver.find_element_by_xpath('//*[@id="verifyImg"]').get_attribute('src') 14 yanzhengma = requests.get(src) 15 #将验证码下载到本地 16 with open('yanzhengma.jpg','wb') as file: 17 file.write(yanzhengma.content)
18 #使用超级鹰识别下载到本地的验证码 19 #定义Chaojiying_Client类的代码是超级鹰官网自带的 20 from hashlib import md5 21 class Chaojiying_Client(object): 22 def __init__(self, username, password, soft_id): 23 self.username = username 24 self.password = md5(password.encode('utf8')).hexdigest() 25 self.soft_id = soft_id 26 self.base_params = { 27 'user': self.username, 28 'pass2': self.password, 29 'softid': self.soft_id, 30 } 31 self.headers = { 32 'Connection': 'Keep-Alive', 33 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', 34 } 35 def PostPic(self, im, codetype): 36 """ 37 im: 图片字节 38 codetype: 题目类型 参考 http://www.chaojiying.com/price.html 39 """ 40 params = { 41 'codetype': codetype, 42 } 43 params.update(self.base_params) 44 files = {'userfile': ('ccc.jpg', im)} 45 r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers) 46 return r.json() 47 def ReportError(self, im_id): 48 """ 49 im_id:报错题目的图片ID 50 """ 51 params = { 52 'id': im_id, 53 } 54 params.update(self.base_params) 55 r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers) 56 return r.json() 57 chaojiying = Chaojiying_Client('账号', '密码', '软件ID') 58 im = open('yanzhengma.jpg', 'rb').read() 59 60 #将超级鹰识别的验证码传入网页中输入验证码的位置。chaojiying.PostPic(im,1004)['pic_str']是超级鹰识别验证码的结果。 61 driver.find_element_by_xpath('//*[@id="verity"]').send_keys(chaojiying.PostPic(im, 1004)['pic_str'])
62 #点击登陆 63 driver.find_element_by_xpath('//*[@id="userLogin"]/div[4]/button').click()
运行后的bug
运行后发现自动输入验证码时与网页上显示的验证码并不一致。经过思考后,明白了问题出在思路的第三步。因为网页上显示的验证码是我们第一次请求滴滴打码时的验证码,而自动输入的验证码是我们第二次重新请求下载到本地的验证码。这两次请求的验证码并不是同一个,所以就出现了这个bug。即思路的第三步并不可行。
解决——思路的第三步
1 使用selenium截取全屏,然后再截取全屏中特定区域(即验证码的区域)的图片。
例如:①使用selenium截取百度网页全屏
1 driver = webdriver.Chrome() 2 wait = WebDriverWait(driver, 10) 3 driver.get('https://www.baidu.com') 4 time.sleep(3) 5 6 # 用 get_screenshot_as_file('绝对路径') 方法来截取全屏,并把截取的全屏保存到绝对路径。 7 # 注:保存的图片格式必须为png。 8 driver.get_screenshot_as_file('C:Usersdesktopquanping.png')
②截取全屏中特定区域(验证码)的图片
1 from PIL import Image 2 # 对验证码所在位置进行定位,注意定位时电脑的缩放布局必须要设置为100%,不然定位不准确。 3 img = driver.find_element_by_xpath('***') 4 time.sleep(2) 5 6 # location属性以字典的形式返回该图片对象(既这张图片)在浏览器中的坐标。假设图片的坐标是(30,30) 即返回{‘x’:30,‘y’:30} 坐标轴是以屏幕左上角为原点,x轴向右递增,y轴向下递增。 7 location = img.location 8 # size属性以字典的形式返回该图片对象(即这张图片)的宽度和高度。假设图片的宽度和高度均为30,即返回{‘height’:30,‘width’:30} 9 size = img.size 10 11 left = location['x'] 12 top = location['y'] 13 right = left + size['width'] 14 bottom = top + size['height'] 15 16 # pillow模块使用crop((left, up, right, below))方法来裁剪图片 17 obj = Image.open('quanping.png') 18 yanzhengma = obj.crop((left, top, right, bottom)) 19 # yanzhengma.show() 20 21 # 把截取到的验证码图片下载到本地。 22 Image.save('yanzhengma.png')
2 使用超级鹰对下载到本地的验证码进行识别。
3 把超级鹰识别后的验证码传送到网页中输入验证码的位置。
1 '''2020-7-2 by 微风''' 2 3 from selenium import webdriver 4 import requests 5 6 #打开谷歌浏览器 7 driver = webdriver.Chrome(r'D:Python37Libchromedriver.exe') 8 #打开浏览器后发送get请求 9 driver.get('http://www.ddocr.com/user/login.html') 10 #将浏览器最大化显示 11 driver.maximize_window() 12 13 driver.find_element_by_xpath('//*[@id="account"]').send_keys('账号') 14 driver.find_element_by_xpath('//*[@id="password"]').send_keys('密码') 15 16 from PIL import Image 17 driver.get_screenshot_as_file('D:PycharmProjects爬虫quanping.png') 18 obj = Image.open('quanping.png') 19 20 # 要注意截取验证码时电脑的缩放布局必须要设置为100%,不然定位不准确。 21 location = driver.find_element_by_xpath('//*[@id="verifyImg"]').location 22 size = driver.find_element_by_xpath('//*[@id="verifyImg"]').size 23 24 left = location['x'] 25 top = location['y'] 26 right = left + size['width'] 27 bottom = top + size['height'] 28 yanzhengma = obj.crop((left,top,right,bottom)) 29 yanzhengma.save('yanzhengma.png') 30 31 #使用超级鹰识别下载到本地的验证码 32 #定义Chaojiying_Client类的代码是超级鹰官网自带的 33 from hashlib import md5 34 class Chaojiying_Client(object): 35 def __init__(self, username, password, soft_id): 36 self.username = username 37 self.password = md5(password.encode('utf8')).hexdigest() 38 self.soft_id = soft_id 39 self.base_params = { 40 'user': self.username, 41 'pass2': self.password, 42 'softid': self.soft_id, 43 } 44 self.headers = { 45 'Connection': 'Keep-Alive', 46 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', 47 } 48 def PostPic(self, im, codetype): 49 """ 50 im: 图片字节 51 codetype: 题目类型 参考 http://www.chaojiying.com/price.html 52 """ 53 params = { 54 'codetype': codetype, 55 } 56 params.update(self.base_params) 57 files = {'userfile': ('ccc.jpg', im)} 58 r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers) 59 return r.json() 60 def ReportError(self, im_id): 61 """ 62 im_id:报错题目的图片ID 63 """ 64 params = { 65 'id': im_id, 66 } 67 params.update(self.base_params) 68 r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers) 69 return r.json() 70 chaojiying = Chaojiying_Client('账号', '密码', '软件ID') 71 im = open('yanzhengma.png', 'rb').read() 72 73 #将超级鹰识别的验证码传入网页中输入验证码的位置。chaojiying.PostPic(im,1004)['pic_str']是超级鹰识别下载到本地的验证码的结果。 74 driver.find_element_by_xpath('//*[@id="verity"]').send_keys(chaojiying.PostPic(im, 1004)['pic_str']) 75 #点击登陆 76 driver.find_element_by_xpath('//*[@id="userLogin"]/div[4]/button').click()
chaojiying.PostPic(im,1004)['pic_str']是超级鹰识别验证码的结果。