其实说出来不怕大家笑话,我在学习爬虫的初始阶段梦想就是实现全自动登录b站并且获取b站里面自己想要获取的数据。如今也终于是实现了这个梦想,很感激csdn各位博主,您们撰写的博客给我带来的很大的帮助,谢谢~
这一次我也总结了一下b站点触验证码的破解和b站的完整登录,希望能够帮助到需要的人,下面开始分析讲解。
1、需要用到的库
import time
import requests
from PIL import Image
from io import BytesIO
from selenium import webdriver
from chaojiying_Python import chaojiying
from selenium.webdriver.common.action_chains import ActionChains
虽然有点小多,但是除了超级鹰,大部分还都算是常用的库,问题还不算大。所以接下来就说一下超级鹰的使用,包括怎么调用超级鹰(就是这个 from chaojiying_Python import chaojiying)
1.1、超级鹰
先给超级鹰做一下简单介绍:超级鹰,全称 超级鹰打码平台 (是个很好用的东西 emmm)
网站链接 :https://www.chaojiying.com/
1、先注册,然后登陆(这个就不教了吧=。=)
2、点击开发文档
3、进入开发文档后,找到自己对应的编程语言,因为我这里是python所以默认就用python了
4、点击(点击这里下载)下载超级鹰文档,下载完成后你就可以得到一个超级鹰文档的压缩包啦
5、解压缩后就能够得到这样一个文件包
咱们运行其中的py文件就可以了
6、打开py文件后我们拉到最下面去就可以在入口处看到这个东西
第一行的三个参数分别是你的超级鹰账号、密码、软件id。
第二行就是要读取的图片路径,rb就不做解释了
第三行1902那个是验证码的类型
7、软件id的获取
我们在网页登陆了超级鹰后会默认进入用户中心,把页面下拉会看到软件id这个字样,点进去
点进去后你们这里一开始是没有这个软件id列表的,我们可以点击上面的生成一个软件id
软件名称随便填,说明不需要填,软件key是自动生成。填完后就点击提交,就可以得到一个软件id。
8、验证码类型的获取
我们直接点击这个价格体系,进去后就可以看到各种验证码类型,我们可以根据具体需求选择具体的验证码类型进行使用,本次b站登录案例我们用的是:9005
9、学分的充值
返回用户中心,点击这个立即充值(进去后选择自定义额度,不要一下子整100进去了哈哈)
至此,超级鹰如何使用也就算是说完了,当然说的不是很完整,但是已经足够我们这个案例取用
2、b站模拟登陆
本次测试用的网站:https://passport.bilibili.com/login
2.1、登陆前准备
def __init__(self):
"""
self.user_name:b站登录账号
self.password:b站登录密码
self.chaojiying_user_name:超级鹰登录账号
self.chaojiying_password:超级鹰登陆密码
self.chaojiying_ID:超级鹰软件ID
self.chaojiying_kind:超级鹰验证码类型
:return:None
"""
self.url = 'https://passport.bilibili.com/login'
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.username = 'B站账号'
self.password = 'B站密码'
self.chaojiying_user_name = '超级鹰账号'
self.chaojiying_password = '超级鹰密码'
self.chaojiying_ID = '超级鹰软件id'
self.pic_id = ''
self.chaojiying = chaojiying.Chaojiying_Client(self.chaojiying_user_name, self.chaojiying_password,
self.chaojiying_ID)
在开始实现登录前先准备好我们的东西,放在初始化方法里面。
self.chaojiying = chaojiying.Chaojiying_Client(self.chaojiying_user_name, self.chaojiying_password, self.chaojiying_ID)
在初始化方法里面的这一条是通过调用了超级鹰py文件里面的方法。跟前面我们说过的调用超级鹰就有关系啦,至于超级鹰怎么导入,你直接把超级鹰解压缩的文件包放在跟你代码的同级目录下然后进行调用from chaojiying_Python import chaojiying
就可以了。
2.2、打开网站
def open(self):
"""
输入b站账号密码
:return:None
"""
self.driver.get(self.url)
self.driver.find_element_by_id('login-username').send_keys(self.username)
self.driver.find_element_by_id('login-passwd').send_keys(self.password)
2.3、获取登录按钮
def get_touclick_button(self):
"""
获取初次验证按钮
:return: 登录按钮
"""
# 获取初始验证按钮
button = self.driver.find_element_by_xpath('//*[@id="geetest-wrap"]/div/div[5]/a[1]')
return button
2.4、获取点触验证码并且进行验证码的处理
def pick_code(self):
"""
获得点触验证码并且进行点触验证码的处理
:return: None
"""
time.sleep(3)
# 获取点触图片的标签
pick_img_label = self.driver.find_element_by_css_selector('img.geetest_item_img')
# 获取点触图片的链接
src = pick_img_label.get_attribute('src')
response = requests.get(src).content
# 文件的读写
f = BytesIO()
f.write(response)
img = Image.open(f)
# 获取图片与浏览器该标签的大小比例
scale = [pick_img_label.size['width'] / img.size[0],
pick_img_label.size['height'] / img.size[1]]
# 调用超级鹰
cjy = chaojiying.Chaojiying_Client(self.chaojiying_user_name, self.chaojiying_password, self.chaojiying_ID)
result = cjy.PostPic(response, 9005)
# 对结果进行分析
position = result['pic_str'].split('|')
position = [[int(j) for j in i.split(',')] for i in position]
if result['err_no'] == 0:
for item in position:
ActionChains(self.driver).move_to_element_with_offset(pick_img_label, item[0] * scale[0],
item[1] * scale[1]).click().perform()
time.sleep(1)
time.sleep(2)
btn = self.driver.find_element_by_css_selector('div.geetest_commit_tip')
time.sleep(1)
btn.click()
从代码量上来看不难看出这个地方就是整个登录最难的地方了。有几个点我在自己做的时候遇到过一些问题,跟大家分享一下。
2.4.1、获取图片与浏览器该标签的大小比例
scale = [pick_img_label.size['width'] / img.size[0],
pick_img_label.size['height'] / img.size[1]]
这个地方是一定必要的,如果你不去获取图片和浏览器的大小比例,后面你点击的时候就会发现他会点不到
2.4.2、调用超级鹰
cjy = chaojiying.Chaojiying_Client(self.chaojiying_user_name, self.chaojiying_password, self.chaojiying_ID)
result = cjy.PostPic(response, 9005)
result运行出来的最后结果:{'err_no': 0, 'err_str': 'OK', 'pic_id': '1162317367529700100', 'pic_str': '145, 59|245, 255|158, 271|241, 150', 'md5': '188f2726a81e33871e57b57be76b71ef'}
我们先记住这个结果,接着往下看
2.4.3、pic_str 对结果进行分析
pic_str,(字符串) 识别出的结果。对坐标进行分析,通过split和循环嵌套把坐标解析成我们需要的方法
最后的结果是:[[145, 59], [245, 255], [158, 271], [241, 150]]
这个样子的(当然每幅图片坐标肯定是不一样的,所以你们这个位置的值也会跟我不一样,很正常)
2.4.4、err_no
err_no,(数值) 返回代码,如果返回的是0就代表成功返回了。我们加一个判断,返回0就进行点击操作
if result['err_no'] == 0:
for item in position:
ActionChains(self.driver).move_to_element_with_offset(pick_img_label, item[0] * scale[0],
item[1] * scale[1]).click().perform()
2.5、登陆失败时候的处理
一般来说打码平台也不是百分之一百的能够登录成功的,这时候我们就需要对他进行一个判断,让验证码识别失败的重新的进行识别。我们可以通过判断url是否切换来判断是否登录成功。代码如下:
def detect(self):
"""
登陆失败时的处理
:return:None
"""
current = self.driver.current_url
if (
current == 'https://passport.bilibili.com/account/security#/home' or
current == 'https://www.bilibili.com/'):
print('Success!!')
else:
self.chaojiying.ReportError(self.pic_id)
self.pick_code()
self.detect()
至此,b站的点出模拟登录也就算是结束了,再次感谢csdn各位大佬们的帮助。下面放出完整代码,有不对的地方也希望大家能指正出来,谢谢~~
import time
import requests
from PIL import Image
from io import BytesIO
from selenium import webdriver
from chaojiying_Python import chaojiying
from selenium.webdriver.common.action_chains import ActionChains
class BiliiliSpider(object):
def __init__(self):
"""
self.user_name:b站登录账号
self.password:b站登录密码
self.chaojiying_user_name:超级鹰登录账号
self.chaojiying_password:超级鹰登陆密码
self.chaojiying_ID:超级鹰软件ID
self.chaojiying_kind:超级鹰验证码类型
:return:None
"""
self.url = 'https://passport.bilibili.com/login'
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.username = '18676556724'
self.password = '1997yx0912'
self.chaojiying_user_name = 'chatblanc'
self.chaojiying_password = '1997yx0912'
self.chaojiying_ID = 925932
self.pic_id = ''
self.chaojiying = chaojiying.Chaojiying_Client(self.chaojiying_user_name, self.chaojiying_password,
self.chaojiying_ID)
def open(self):
"""
输入b站账号密码
:return:None
"""
self.driver.get(self.url)
self.driver.find_element_by_id('login-username').send_keys(self.username)
self.driver.find_element_by_id('login-passwd').send_keys(self.password)
def get_touclick_button(self):
"""
获取初次验证按钮
:return: 登录按钮
"""
# 获取初始验证按钮
button = self.driver.find_element_by_xpath('//*[@id="geetest-wrap"]/div/div[5]/a[1]')
return button
def pick_code(self):
"""
获得点触验证码并且进行点触验证码的处理
:return: None
"""
time.sleep(3)
# 获取点触图片的标签
pick_img_label = self.driver.find_element_by_css_selector('img.geetest_item_img')
# 获取点触图片的链接
src = pick_img_label.get_attribute('src')
response = requests.get(src).content
# 文件的读写
f = BytesIO()
f.write(response)
img = Image.open(f)
# 获取图片与浏览器该标签的大小比例
scale = [pick_img_label.size['width'] / img.size[0],
pick_img_label.size['height'] / img.size[1]]
# 调用超级鹰
cjy = chaojiying.Chaojiying_Client(self.chaojiying_user_name, self.chaojiying_password, self.chaojiying_ID)
result = cjy.PostPic(response, 9005)
# 对结果进行分析
position = result['pic_str'].split('|')
position = [[int(j) for j in i.split(',')] for i in position]
if result['err_no'] == 0:
for item in position:
ActionChains(self.driver).move_to_element_with_offset(pick_img_label, item[0] * scale[0],
item[1] * scale[1]).click().perform()
time.sleep(1)
time.sleep(2)
# 定位确定按钮
btn = self.driver.find_element_by_css_selector('div.geetest_commit_tip')
time.sleep(1)
btn.click()
def detect(self):
"""
登陆失败时的处理
:return:None
"""
current = self.driver.current_url
if (
current == 'https://passport.bilibili.com/account/security#/home' or
current == 'https://www.bilibili.com/'):
print('Success!!')
else:
self.chaojiying.ReportError(self.pic_id)
self.pick_code()
self.detect()
def main(self):
"""
主函数
:return:None
"""
self.open()
time.sleep(2)
button = self.get_touclick_button()
button.click()
self.pick_code()
time.sleep(2)
# self.detect()
if __name__ == '__main__':
bilibili = BiliiliSpider()
bilibili.main()