超级鹰
在这个项目中使用超级鹰来识别验证码。超级鹰的官方接入文档如下。
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:\Python37\Lib\chromedriver.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:\Users\desktop\quanping.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:\Python37\Lib\chromedriver.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\']是超级鹰识别验证码的结果。