最新验证码识别模拟登陆B站

Python中文社区

共 4357字,需浏览 9分钟

 ·

2021-02-02 08:51

「本文目录」

  • 1 分析登录界面结构
  • 2 使用selenium打开登录页面
  • 3 获取页面当前验证码图片
  • 4 使用超级鹰识别验证码
  • 5 对获取的坐标数据进行提取,并用动作链完成点击

1 分析登录界面结构

首先明确我们的目标,打开登陆界面,定位用户名和密码对应的标签,输入相关数据后,点击登录,此时页面会弹出验证码。

下面用两种方法进行验证码的获取,然后提交给「超级鹰」进行识别,接收到汉字的坐标后,处理数据,然后用动作链进行点击操作,最后定位点击确认,登陆成功。

2 使用selenium打开登录页面

「代码实现:」

# 使用selenium打开登录界面
bro = webdriver.Chrome(executable_path='./chromedriver')
bro.get('https://passport.bilibili.com/login')

# 定位用户名,密码输入框
username = bro.find_element_by_id('login-username')
password = bro.find_element_by_id('login-passwd')

sleep(1)
# 将自己的用户名密码替换xxxxxx
username.send_keys('xxxxxx')
sleep(1)
password.send_keys('xxxxxx')
sleep(1)

# 定位登录按钮并点击
bro.find_element_by_xpath('//*[@id="geetest-wrap"]/div/div[5]/a[1]').click()
sleep(2)

3 获取页面当前验证码图片

3.1 方法一:页面截图,将验证码区域进行裁剪保存

使用此方法时,注意我们截取验证码图片时需要截取完整,完整验证码截图如下:

首先做的当然是将点击登录后的页面进行截图,然后定位到验证码的位置,通过location()方法获取验证码左上角的坐标, size() 获取验证码的宽和高,左上角坐标加上宽和高就是验证码右下角的坐标。获取坐标后就可以用crop()方法来进行裁剪,然后将裁剪到的验证码图片保存。

此时虽然获取了验证码图片,但是还不能直接提交给超级鹰。
因为超级鹰识别的验证码图片的宽和高有限制,最好不超过460px*310px
但是截取到的验证码图片宽高为338px*432px,这时就要先将图片缩小一倍再提交即可,等到收到坐标数据再将坐标乘2

「代码实现:」
# 本文相关完整代码可以关注微信公众号:简说Python,回复:B站 获取。
# save_screenshot就是将当前页面进行截图且保存
bro.save_screenshot('page.png')

# 定位验证码图片的位置
code_img_ele = bro.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  # 验证码图片对应的长和宽

# 左上角和右下角的坐标
# 这里坐标乘1.25是由于电脑屏幕的比例不是100%,我的是125%,请自行在设置中查看
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)
)

i = Image.open('./page.png')
code_img_name = './code.png'
# crop根据rangle元组内的坐标进行裁剪
frame = i.crop(rangle)
frame.save(code_img_name)

# 缩小图片,宽为169,高为216
code = Image.open('./code.png')
small_img = code.resize((169216))
small_img.save('./small_img.png')
print(code.size, small_img.size)

3.2方法二、通过网页获取图片地址,并保存

这种方法比上一种更加方便,分析网页源码获取图片地址,对该地址发送请求,接收返回的二进制文件,进行保存。首先打开网页源码找到图片地址。

图片地址是img标签的src属性值,通过xpath得到地址,直接对此url发送请求,接收数据并保存即可。

「注意:」 由于获取的图片的高度仍然大于超级鹰标准格式,所以也需要将图片缩小。
「代码实现:」
# 本文相关完整代码可以关注微信公众号:简说Python,回复:B站 获取。
# 获取img标签的src属性值
img_url = bro.find_element_by_xpath('/html/body/div[2]/div[2]/div[6]/div/div/div[2]/div[1]/div/div[2]/img').get_attribute('src')
headers = {
    'Users-Agent''Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36'
}
# 获取图片二进制数据
img_data = requests.get(url=img_url, headers=headers).content
with open('./node1.png''wb')as fp:
    fp.write(img_data)
i = Image.open('./node1.png')
# 将图片缩小并保存,设置宽为172,高为192
small_img = i.resize((172192))
small_img.save('./small_img1.png')

4 使用超级鹰识别验证码

这部分没什么说的,直接调用就行。
「代码如下:」
# 本文相关完整代码可以关注微信公众号:简说Python,回复:B站 获取。
# 将验证码提交给超级鹰进行识别
chaojiying = Chaojiying_Client('用户名''密码''96001')  # 用户中心>>软件ID 生成一个替换 96001
im = open('small_img.png''rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
# 9004是验证码类型
print(chaojiying.PostPic(im, 9004)['pic_str'])
result = chaojiying.PostPic(im, 9004)['pic_str']

5 对获取的坐标数据进行提取,并用动作链完成点击

超级鹰识别返回的数据格式是:123,12 | 234,21。
我们可以将数据以' | '进行分割,保存到列表中,再以逗号分割将x,y的坐标保存,得到[ [123,12],[234,21] ]这一格式,然后遍历这一列表,使用动作链对每一个列表元素对应的x,y指定的位置进行点击操作,最后定位并点击确认,登录成功。

「代码实现:」

# 本文相关完整代码可以关注微信公众号:简说Python,回复:B站 获取。
all_list = []  # 要存储即将被点击的点的坐标  [[x1,y1],[x2,y2]]
if '|' in result:
    list_1 = result.split('|')
    count_1 = len(list_1)
    for i in range(count_1):
        xy_list = []
        x = int(list_1[i].split(',')[0])
        y = int(list_1[i].split(',')[1])
        xy_list.append(x)
        xy_list.append(y)
        all_list.append(xy_list)
else:
    x = int(result.split(',')[0])
    y = int(result.split(',')[1])
    xy_list = []
    xy_list.append(x)
    xy_list.append(y)
    all_list.append(xy_list)

# 遍历列表,使用动作链对每一个列表元素对应的x,y指定的位置进行点击操作
# x,y坐标乘2和0.8,是由于
for l in all_list:
    x = l[0] * 2 * 0.8
    y = l[1] * 2 * 0.8
    # 将点击操作的参照物移动到指定的模块,
    # 若用方法二获取的验证码图片,要添加下面代码对code_img_ele赋值
    # code_img_ele = bro.find_element_by_xpath('/html/body/div[2]/div[2]/div[6]/div/div/div[2]/div[1]/div/div[2]/img')
    ActionChains(bro).move_to_element_with_offset(code_img_ele, x, y).click().perform()
    sleep(0.1)
    print('点击已完成')

# 完成动作链点击操作后,定位确认按钮并点击
bro.find_element_by_xpath('/html/body/div[2]/div[2]/div[6]/div/div/div[3]/a').click()

更多阅读



2020 年最佳流行 Python 库 Top 10


2020 Python中文社区热门文章 Top 10


5分钟快速掌握 Python 定时任务框架

特别推荐




点击下方阅读原文加入社区会员

浏览 67
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报