python模拟哔哩哔哩滑块登入验证的实现

1. 前言

最近在写一个爬虫项目,需要模拟哔哩哔哩的登入。但是,哔哩哔哩使用了滑块登入验证,传统的表单提交加上账号密码的方式已经不能满足需求。本文将介绍如何使用 Python 模拟哔哩哔哩的滑块登入验证。

2. 环境准备

2.1 安装 Python

首先,要确保你已经安装了 Python。如果你还没有安装 Python,请到 Python官网 下载对应版本。

2.2 安装 selenium

在本文中,我们将使用 selenium 来模拟登入。selenium 是一个自动化测试工具,可以模拟用户在浏览器中的操作。

使用 pip 安装最新版本的 selenium:

pip install selenium

2.3 下载 Chromedriver

selenium 需要一个浏览器驱动程序才能模拟浏览器。在本文中,我们将使用 Chrome 浏览器。请到 Chromedriver 官网 下载对应版本的 Chromedriver。下载后,将 Chromedriver.exe 文件放在任意一个文件夹中。

3. 实现

3.1 打开 Chrome 浏览器

使用 Python 中的 selenium webdriver,打开 Chrome 浏览器:

from selenium import webdriver

# 初始化浏览器

browser = webdriver.Chrome(r"C:\path\to\chromedriver.exe")

这里需要把 r"C:\path\to\chromedriver.exe" 替换成 Chromedriver 的实际路径。

3.2 进入哔哩哔哩登入页面

使用 get() 方法进入哔哩哔哩登入页面:

# 进入登入页面

browser.get('https://passport.bilibili.com/login')

3.3 切换到滑动验证码的 iframe

哔哩哔哩的滑块登入验证是在一个 iframe 中进行的。因此,需要使用 switch_to.frame() 方法切换到滑动验证码的 iframe 中:

# 切换到滑动验证码的 iframe

iframe = browser.find_element_by_xpath('//iframe[@id="gc-box"]')

browser.switch_to.frame(iframe)

3.4 获取滑块和背景图片的 URL

哔哩哔哩的滑动验证码需要使用背景图片和滑块图片进行验证。使用 get_attribute() 方法获取背景图片和滑块图片的 URL:

# 获取背景图片

background_img = browser.find_element_by_xpath('//div[@class="gt_cut_bg gt_show"]/div[@class="gt_cut_bg_slice"]')

bg_url = background_img.get_attribute('style').split("'")[1]

# 获取滑块图片

slider_img = browser.find_element_by_xpath('//div[@class="gt_cut_fullbg gt_show"]/div[@class="gt_cut_fullbg_slice"]')

slider_url = slider_img.get_attribute('style').split("'")[1]

这里需要注意一下,获取到的背景图片和滑块图片的 URL 包含了一些参数。这些参数是每次请求时生成的,需要在每次请求时重新获取。

3.5 下载背景图片和滑块图片并还原

哔哩哔哩的滑块验证码还原需要将背景图片和滑块图片拼接在一起,并根据图片的不同特点还原出完整的滑动验证码。这个过程可以使用 PIL 库来实现。

首先,使用 requests 库下载图片:

import requests

# 下载背景图片和滑块图片

bg = requests.get(bg_url).content

slider = requests.get(slider_url).content

然后,使用 PIL 库将图片转换为 Image 对象:

from PIL import Image

from io import BytesIO

# 将图片转换为 Image 对象

bg = Image.open(BytesIO(bg))

slider = Image.open(BytesIO(slider))

最后,根据图片的不同特点还原出完整的滑动验证码:

import re

import time

import random

# 还原滑动验证码

def get_offset(bg, slider):

# 阈值

threshold = 50

# 获取要滑动的距离

for x in range(bg.size[0] - slider.size[0]):

for y in range(bg.size[1] - slider.size[1]):

# 计算每个像素点的 RGB 值之和

bg_rgb = sum(bg.getpixel((x, y)))

slider_rgb = sum(slider.getpixel((x, y)))

# 如果 RGB 值之和之差超过了阈值,说明找到了要滑动的距离

if abs(bg_rgb - slider_rgb) > threshold:

return x

# 根据 RGB 值还原滑动验证码

def restore_image(im_path, bg_path, u, x):

im = Image.open(im_path)

bg = Image.open(bg_path)

# 将滑块放到正确的位置

bg.paste(im, (x, 0))

# 获取阴影部分

img1 = bg.crop((u, 0, u + im.size[0], im.size[1]))

# 获取拼图部分

img2 = im.crop((0, 0, im.size[0], im.size[1]))

# 创建一张新的图片

new_img = Image.new('RGB', (bg.size[0], bg.size[1]))

# 将阴影部分放到新图片中

new_img.paste(img1, (0, 0))

# 将拼图部分放到新图片中

new_img.paste(img2, (x, 0))

# 返回还原后的图片

return new_img

这个过程看起来比较复杂,但实际上就是比较简单的图像处理。如果你对图像处理的原理感兴趣,可以自行查阅相关资料。

3.6 拖动滑块完成验证

最后,使用 ActionChains 类拖动滑块完成验证:

from selenium.webdriver.common.action_chains import ActionChains

# 拖动滑块完成验证

slider_btn = browser.find_element_by_xpath('//div[@class="gt_slider_knob gt_show"]')

ActionChains(browser).click_and_hold(slider_btn).perform()

# 还原图片并获取要滑动的距离

bg_path = 'bg.png'

im_path = 'slider.png'

bg.save(bg_path)

slider.save(im_path)

u = get_offset(bg, slider)

# 根据 RGB 值还原滑动验证码

new_img = restore_image(im_path, bg_path, u, 0)

new_img.save('new.png')

# 拖动滑块完成验证

ActionChains(browser).move_by_offset(u, 0).perform()

ActionChains(browser).release().perform()

这里需要注意一下,move_by_offset(u, 0) 中的 u 就是之前还原图片时计算得到的要滑动的距离。

4. 完整代码

from selenium import webdriver

from selenium.webdriver.common.action_chains import ActionChains

from PIL import Image

from io import BytesIO

import requests

browser = webdriver.Chrome(r"C:\path\to\chromedriver.exe")

browser.get('https://passport.bilibili.com/login')

# 切换到滑动验证码的 iframe

iframe = browser.find_element_by_xpath('//iframe[@id="gc-box"]')

browser.switch_to.frame(iframe)

# 获取背景图片

background_img = browser.find_element_by_xpath('//div[@class="gt_cut_bg gt_show"]/div[@class="gt_cut_bg_slice"]')

bg_url = background_img.get_attribute('style').split("'")[1]

# 获取滑块图片

slider_img = browser.find_element_by_xpath('//div[@class="gt_cut_fullbg gt_show"]/div[@class="gt_cut_fullbg_slice"]')

slider_url = slider_img.get_attribute('style').split("'")[1]

# 下载背景图片和滑块图片

bg = requests.get(bg_url).content

slider = requests.get(slider_url).content

# 将图片转换为 Image 对象

bg = Image.open(BytesIO(bg))

slider = Image.open(BytesIO(slider))

# 还原滑动验证码

def get_offset(bg, slider):

# 阈值

threshold = 50

# 获取要滑动的距离

for x in range(bg.size[0] - slider.size[0]):

for y in range(bg.size[1] - slider.size[1]):

# 计算每个像素点的 RGB 值之和

bg_rgb = sum(bg.getpixel((x, y)))

slider_rgb = sum(slider.getpixel((x, y)))

# 如果 RGB 值之和之差超过了阈值,说明找到了要滑动的距离

if abs(bg_rgb - slider_rgb) > threshold:

return x

def restore_image(im_path, bg_path, u, x):

im = Image.open(im_path)

bg = Image.open(bg_path)

# 将滑块放到正确的位置

bg.paste(im, (x, 0))

# 获取阴影部分

img1 = bg.crop((u, 0, u + im.size[0], im.size[1]))

# 获取拼图部分

img2 = im.crop((0, 0, im.size[0], im.size[1]))

# 创建一张新的图片

new_img = Image.new('RGB', (bg.size[0], bg.size[1]))

# 将阴影部分放到新图片中

new_img.paste(img1, (0, 0))

# 将拼图部分放到新图片中

new_img.paste(img2, (x, 0))

# 返回还原后的图片

return new_img

slider_btn = browser.find_element_by_xpath('//div[@class="gt_slider_knob gt_show"]')

ActionChains(browser).click_and_hold(slider_btn).perform()

bg_path = 'bg.png'

im_path = 'slider.png'

bg.save(bg_path)

slider.save(im_path)

u = get_offset(bg, slider)

new_img = restore_image(im_path, bg_path, u, 0)

new_img.save('new.png')

ActionChains(browser).move_by_offset(u, 0).perform()

ActionChains(browser).release().perform()

5. 总结

本文介绍了如何使用 Python 模拟哔哩哔哩的滑块登入验证。具体来说,我们使用 selenium 打开 Chrome 浏览器,然后进入哔哩哔哩的登入页面。接下来,我们使用 selenium 切换到滑动验证码的 iframe,并获取滑块和背景图片的 URL。然后,我们使用 requests 库下载背景图片和滑块图片,并使用 PIL 库还原出完整的滑动验证码。最后,我们使用 ActionChains 类拖动滑块完成验证。

这里仅仅是一个简单的例子,实际上滑动验证码常常被应用于诸如网站爬虫、反爬虫、登录验证等场景。理解滑动验证码的原理以及如何模拟它的行为,对爬虫优化或反爬虫工作是有很大帮助的。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。

后端开发标签