如今网站的的普滑动验证码一已经逐渐替代普通的验证码
这无疑加大了爬虫的工作量
滑动验证码可以显著优化用户体验,这在互联网时代是非常重要的。
通过这次实践我也学到了很多
今天我们以bilibili为例讲解破解滑动验证码的过程
关于selenium的介绍及安装请看我另一篇博客:
需要用到的库
from PIL import ImageChops, Image
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import pyautogui
from time import sleep
import os
首先利用selenium自动填充用户名,密码并点击登录
driver = webdriver.Chrome()
ac = ActionChains(driver)
driver.implicitly_wait(3)
driver.get('https://passport.bilibili.com/login')
driver.maximize_window()
# 输入账号和密码
input1 = driver.find_element_by_xpath('//div//input[@id="login-username"]').send_keys('18888888888')
input2 = driver.find_element_by_xpath('//div//input[@id="login-passwd"]').send_keys('xxxxxxxx')
driver.find_element_by_xpath('//div/a[@class="btn btn-login"]').click() # 点击登录按钮
sleep(1)
获取滑动验证码的背景图和带缺口的背景图
# 获取带缺口的图片
js = 'document.getElementsByClassName("geetest_canvas_slice")[0].className="geetest_canvas_slice geetest_absolute1"'
driver.execute_script(js)
img = driver.find_element_by_xpath('//*[@class="geetest_canvas_slice geetest_absolute1"]')
ac.context_click(img).perform()
pyautogui.typewrite(['enter', 'enter', 'enter'])
利用js修改class类命达到隐藏滑块就可以很轻松得到带缺口的背景图
# 获取完整的背景图片
js = 'document.getElementsByClassName("geetest_canvas_fullbg geetest_fade geetest_absolute")[0].style=""'
driver.execute_script(js)
img = driver.find_element_by_xpath('//*[@class="geetest_canvas_slice geetest_absolute1"]')
ac.context_click(img).perform()
pyautogui.typewrite(['enter', 'enter', 'enter'])
再通过删除style获取完整的背景图
# 恢复出带缺口的图片便于滑动时是观察(可选)
js = 'document.getElementsByClassName("geetest_canvas_slice")[0].className="geetest_canvas_slice geetest_absolute"'
driver.execute_script(js)
前面两部会删除滑块,不利于观察,加上这两句可以使原来的滑块恢复,即把类名改回原来的
对比两张图片找到缺口位置计算滑动多少像素
table = []
for i in range(256):
if i < 50:
table.append(0)
else:
table.append(1)
def compute_gap(img1, img2):
"""计算缺口偏移 这种方式成功率很高"""
# 将图片修改为RGB模式
img1 = img1.convert("RGB")
img2 = img2.convert("RGB")
# 计算差值
diff = ImageChops.difference(img1, img2)
# 灰度图
diff = diff.convert("L")
# 二值化
diff = diff.point(table, '1')
left = 42
for w in range(left, diff.size[0]):
lis = []
for h in range(diff.size[1]):
if diff.load()[w, h] == 1:
lis.append(w)
if len(lis) > 5:
return w
# 从下载中获取两张图片
def get_images():
bg = Image.open('C:/Users/yuaneuro/Downloads/下载.png')
fullgb = Image.open('C:/Users/yuaneuro/Downloads/下载 (1).png')
return bg, fullgb
最后编写主函数
def main():
bg_img, fullbg_img = get_images()
gap = compute_gap(fullbg_img, bg_img)
print(gap)
# 寻找滑块的元素
slide = driver.find_element_by_xpath('//*[@class="geetest_slider_button"]')
ac = ActionChains(driver)
# 滑动操作(等待大佬更新滑动算法)
ac.click_and_hold(slide).perform()
ac.move_by_offset(gap - 10, 0.1).perform() # 平行移动鼠标
slide.click()
ac.reset_actions()
if __name__ == '__main__':
main()
os.remove('C:/Users/yuaneuro/Downloads/下载.png')
os.remove('C:/Users/yuaneuro/Downloads/下载 (1).png')
这里滑动验证码已经更新,暂未找到合适有效的滑动轨迹的方法,暂时用最原始的替代,后续找到可以用的滑动轨迹会跟新!
完整代码
此处内容需要评论回复后(审核通过)方可阅读。
11 条评论
学习一下
学习
学习一下
学习一下
照片没有下载下来耶
学习一下大佬操作
xuexi yixia
学习一下
参考一下,获取不到完整图(╯‵□′)╯︵┴─┴
学习一下
看看大神