AI派在读学生小姐姐Beyonce
Java实战项目练习群
长按识别下方二维码,按需求添加
扫码添加Beyonce小姐姐
扫码关注
进Java学习大礼包
来源:Python数据之道
作者:叶庭云
整理:Lemon
验证码多种多样,有图形文字的、有模拟点选的、有拖动滑动的,但其实归根结底都需要人来对某种情形做一些判断,然后把结果返回并提交。
如果此时提交的验证码结果是正确的,并且通过了一些验证码的检测,就能成功突破这个验证码了。既然验证码就是让人来识别的,那么机器怎么办呢?
如果我们也不会什么算法,怎么去解这些验证码呢?此时我们需要利用可以帮助我们来识别验证码的工具或平台就,让工具或平台把验证码识别的结果返回给我们,我们拿着结果提交,那不就好了吗?
有专门的打码平台帮助我们来识别各种各样的验证码,平台内部对算法和人力做了集成,可以 7x24 小时来识别各种验证码,包括识别图形、坐标点、缺口等各种验证码,返回对应的结果或坐标,正好可以解决我们的问题,比如超级鹰。
B站最新登录验证为点选验证码,以模拟登录 B 站来熟悉 selenium 库的使用和打码平台的使用方法。
这个验证码上面显示了几个汉字,同时在图中也显示了几个汉字,我们需要按照顺序依次点击汉字在图中的位置,点击完成之后确认提交,即可完成验证。这种验证码如果我们没有任何图像识别算法基础的话,是很难去识别的,所以这里我们可以借助打码平台来帮助我们识别汉字的位置。
本文用到的 Python 库是 Selenium,使用的浏览器为 Chrome,确保已经正确安装好 Selenium 库、Chrome 浏览器,并配置好 ChromeDriver,
使用的打码平台是超级鹰,链接为:https://www.chaojiying.com/,在使用之前请读者自行注册账号并获取一些题分供测试,另外还可以了解平台可识别的验证码的类别。
打码平台能提供的服务种类一般都非常广泛,可识别的验证码类型也非常多,其中就包括点触验证码。
超级鹰平台同样支持简单的图形验证码识别,超级鹰平台提供了如下一些服务:
英文数字:提供最多 20 位英文数字的混合识别;
中文汉字:提供最多 7 个汉字的识别;
纯英文:提供最多 12 位的英文识别;
纯数字:提供最多 11 位的数字识别;
任意特殊字符:提供不定长汉字英文数字、拼音首字母、计算题、成语混合、集装箱号等字符的识别;
坐标选择识别:如复杂计算题、选择题四选一、问答题、点击相同的字、物品、动物等返回多个坐标的识别;
本例需要处理的就是坐标多选识别的情况。我们先将验证码图片提交给平台,平台会返回识别结果在图片中的坐标位置,然后我们再解析坐标模拟点击,下面我们就用程序来实现。
通过官方网站下载对应的 Python API,链接为:https://www.chaojiying.com/api-14.html。API 是 Python 2 版本的,用 requests 库来实现的。我们可以简单更改几个地方,即可将其修改为 Python 3 版本。
修改之后的 API 如下所示:
# -*- coding: UTF-8 -*-
# Chaojiying_Client类 用于提交要识别的图片 返回json结果
class Chaojiying_Client(object):
def __init__(self, username, password, soft_id):
self.username = username
password = password.encode('utf-8')
self.password = md5(password).hexdigest()
self.soft_id = soft_id
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
}
def PostPic(self, im, codetype):
"""
im: 图片字节
codetype: 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files,
headers=self.headers)
logging.info(r.json())
return r.json()
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
logging.info(r.json())
return r.json()
这里定义了一个 Chaojiying 类,其构造函数接收三个参数,分别是超级鹰的用户名、密码以及软件 ID,保存以备使用。
最重要的一个方法叫作 post_pic,它需要传入图片对象和验证码类型的代号。该方法会将图片对象和相关信息发给超级鹰的后台进行识别,然后将识别成功的 json 返回。
另一个方法叫作 report_error,它是发生错误时的回调。如果验证码识别错误,调用此方法会返回相应的题分。
进入登陆界面,定位用户名和密码对应的标签,模拟输入我们的账号和密码,点击登录,此时页面会弹出验证码。
对进行验证码的获取,然后提交给「超级鹰」进行识别,接收到汉字的坐标后,处理数据,然后用动作链进行模拟点击操作,最后定位点击确认,实现成功登录 B 站。
导入用的库
from selenium import webdriver
from time import sleep
from PIL import Image
from selenium.webdriver import ActionChains
import random
import requests
from hashlib import md5
import logging
日志输出和 webdriver.Chrome() 配置
# 日志输出配置
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s')
# 初始化一个webdriver.Chrome()对象
chrome_driver = r'D:\python\pycharm2020\chromedriver.exe'
options = webdriver.ChromeOptions()
# 关闭左上方 Chrome 正受到自动测试软件的控制的提示
options.add_experimental_option('useAutomationExtension', False)
options.add_experimental_option("excludeSwitches", ['enable-automation'])
browser = webdriver.Chrome(options=options, executable_path=chrome_driver)
用 selenium 打开登录页面,进行模拟登录
# 登录函数 访问页面->输出账号、密码->点击登录
def login():
browser.get('https://passport.bilibili.com/login')
browser.maximize_window()
# ID定位用户名,密码输入框
username = browser.find_element_by_id('login-username')
password = browser.find_element_by_id('login-passwd')
username.send_keys('your username')
password.send_keys('your password')
# Xpath定位登录按钮并点击
browser.find_element_by_xpath('//*[@id="geetest-wrap"]/div/div[5]/a[1]').click()
sleep(random.random()*3)
将当前页面进行截图并保存下来,裁剪出验证码区域
def save_img():
# save_screenshot:将当前页面进行截图并保存下来
browser.save_screenshot('page.png')
# Xpath定位验证码图片的位置
code_img_ele = browser.find_element_by_xpath('/html/body/div[2]/div[2]/div[6]/div/div')
location = code_img_ele.location # 验证码左上角的坐标x,y
size = code_img_ele.size # 验证码图片对应的长和宽
# 得到左上角和右下角的坐标
rangle = (
int(location['x'] * 1.25), int(location['y'] * 1.25), int((location['x'] + size['width']) * 1.25),
int((location['y'] + size['height']) * 1.25)
)
image1 = Image.open('./page.png')
# code_img_name = './code.png'
# crop根据rangle元组内的坐标进行裁剪 裁剪出验证码区域
frame = image1.crop(rangle)
frame.save('./code.png')
return code_img_ele
将点击登录后的页面进行截图,然后定位到验证码的位置,通过location()方法获取验证码左上角的坐标, size() 获取验证码的宽和高,左上角坐标加上宽和高就是验证码右下角的坐标。获取坐标后就可以用 crop() 方法来进行裁剪,然后将裁剪到的验证码图片保存。
缩小图片
def narrow_img():
# 缩小图片
code = Image.open('./code.png')
small_img = code.resize((169, 216))
small_img.save('./small_img.png')
print(code.size, small_img.size)
此时虽然获取了验证码图片,但是还不能直接提交给超级鹰。因为超级鹰识别的验证码图片的宽和高有限制,最好不超过460px*310px。但是截取到的验证码图片宽高为338px*432px,这时就要先将图片缩小一倍再提交即可,等到收到坐标数据再将坐标乘2。
将验证码提交给超级鹰进行识别
def submit_img():
# 将验证码提交给超级鹰进行识别
# 用户中心->软件ID 生成你的软件ID->替换掉96001 绑定微信可以得到1000积分 免费使用
chaojiying = Chaojiying_Client('你的用户名', '密码', '生成的软件ID')
with open('./small_img.png', 'rb') as f:
im = f.read()
# 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
result = chaojiying.PostPic(im, 9004)['pic_str']
logging.info(result)
return result
调用已获取的API,传入参数:'你的用户名', '密码','生成的软件ID'
解析返回的汉字的坐标点的结果
def parse_data(result):
node_list = [] # 存储即将被点击的点的坐标 [[x1,y1],[x2,y2]]
print(result)
if '|' in result:
nums = result.split('|')
for i in range(len(nums)):
x = int(nums[i].split(',')[0])
y = int(nums[i].split(',')[1])
xy_list = [x, y]
node_list.append(xy_list)
else:
print(result.split(',')[0])
print(result.split(',')[1])
x = int(result.split(',')[0])
y = int(result.split(',')[1])
xy_list = [x,y]
node_list.append(xy_list)
return node_list
超级鹰识别返回的结果的数据格式为:98,136|87,77 我们可以将数据以' | '进行分割,保存到列表中,再以逗号分割将x,y的坐标保存,得到[ [123,12],[234,21] ]这一格式,然后遍历这一列表,使用动作链对每一个列表元素对应的x,y指定的位置进行模拟点击操作,最后定位并点击确认,可成功实现登录 B 站。
按顺序模拟点击每个坐标点
def click_codeImg(all_list, code_img_ele):
# 遍历列表,使用动作链对每一个列表元素对应的x,y指定的位置进行点击操作
for item in all_list:
x = item[0] * 1.6
y = item[1] * 1.6
# move_to_element_with_offset移动到距某个元素(左上角坐标)多少距离的位置
ActionChains(browser).move_to_element_with_offset(code_img_ele, x, y).click().perform()
sleep(random.random())
logging.info('点击成功!')
sleep(random.random()*2)
# 完成动作链点击操作后,定位确认按钮并点击
browser.find_element_by_xpath('/html/body/div[2]/div[2]/div[6]/div/div/div[3]/a').click()
主函数调用
# -*- coding: UTF-8 -*-
def main():
# 进入登录界面,输入账号密码
login()
# 保存页面截图,并根据坐标裁剪获取验证码图片
code_img_ele = save_img()
# 缩小图片
narrow_img()
# 将图片提交给超级鹰,获取返回的识别结果
result = submit_img()
# 解析返回结果,将数据格式化
all_list = parse_data(result)
# 在页面验证码上完成点击操作并登录
click_codeImg(all_list, code_img_ele)
main()
运行效果如下:
鼠标是放在左边的,没有动过,不是人工悄悄点的哦,这样我们就成功实现了 selenium 模拟登录 B 站。
作者:叶庭云
CSDN:https://yetingyun.blog.csdn.net/
文末福利
各位猿们,还在为记不住API发愁吗,哈哈哈,最近发现了国外大师整理了一份Python代码速查表和Pycharm快捷键sheet,火爆国外,这里分享给大家。
这个是一份Python代码速查表
下面的宝藏图片是2张(windows && Mac)高清的PyCharm快捷键一览图
怎样获取呢?可以添加我们的AI派团队的Beyonce小姐姐
一定要备注【高清图】哦
????????????????????
➕我们的Beyonce小姐姐微信要记得备注【高清图】哦
来都来了,喜欢的话就请分享、点赞、在看三连再走吧~~~