下面是“python 模拟网站登录——滑块验证码的识别”的完整攻略。
简介
对于一些需要登录才能使用的网站,通常都会有验证码来防止自动化登录。其中,滑块验证码是较为常见的一种形式。本文将介绍如何使用 Python 识别并模拟拖动滑块验证码的过程,以实现自动化登录。
技术原理
滑块验证码通常由两部分构成:背景图片和前景图(即要滑动的图块)。由于前景图的位置可变,因此需要通过计算前景图的偏移量,才能模拟拖动过程。
实现的主要步骤如下:
- 获取验证码图片及其位置信息
- 下载、处理图片,得到前景图
- 通过找到两张图片中匹配度最高的位置,计算前景图偏移量
- 模拟鼠标移动及拖动,完成滑块验证码操作
实战演练
以下是两个示例,分别演示了如何识别并拖动一个普通滑块验证码和一个缺口滑块验证码。
示例1:普通滑块验证码
首先通过 Chrome 的开发者工具获取到需要模拟登录的网站的登录界面,找到验证码对应的元素及其在页面中的位置:
<div style="width: 300px; height: 160px; position: relative; overflow: hidden;">
<img src="{验证码url}" style="position: relative; left: -115.231px; top: -40.3074px;">
<div style="position: absolute; left: 95px; top: 20px; z-index: 999; width: 60px; height: 60px; opacity: 0.7; background: rgb(255, 255, 255); border-radius: 30px;"></div>
</div>
可见,背景图片为 "{验证码url}"
,距离左上角的偏移量为 left: -115.231px; top: -40.3074px;
,前景图的初始位置为 left: 95px; top: 20px;
。
接下来,我们需要通过 Python 下载并处理背景图片及其中的前景图。这里使用 Pillow 库来处理图片。代码如下:
from PIL import Image
import requests
session = requests.Session()
# 获取背景图片及其位置信息
bg_url = "{验证码url}"
bg_left = -115.231
bg_top = -40.3074
bg = session.get(bg_url).content
with open("bg.jpg", "wb") as f:
f.write(bg)
# 获取前景图并计算偏移量
front_url = "{前景图url}"
front = session.get(front_url).content
with open("front.png", "wb") as f:
f.write(front)
front_img = Image.open("front.png")
bg_img = Image.open("bg.jpg")
w, h = front_img.size
# 求出前景图在背景图中的位置
real_left = bg_left + 95
real_top = bg_top + 20
# 对比背景图片和前景图中的每个像素,找到相似度最高的位置
for x in range(w):
for y in range(h):
if front_img.getpixel((x, y)) != (0, 0, 0, 0):
bg_x = real_left + x
bg_y = real_top + y
bg_pixel = bg_img.getpixel((bg_x, bg_y))
if abs(bg_pixel[0]-front_img.getpixel((x,y))[0])<10 and abs(bg_pixel[1]-front_img.getpixel((x,y))[1]<10) and abs(bg_pixel[2]-front_img.getpixel((x,y))[2]<10):
move = bg_x - bg_left
break
找到了前景图的偏移量 move
后,接下来的操作就是模拟鼠标拖动前景图。这里使用 Selenium 来完成模拟操作。代码如下:
from selenium import webdriver
from selenium.webdriver import ActionChains
# 模拟鼠标拖动前景图
driver = webdriver.Chrome()
driver.get("{登录页面url}")
slider = driver.find_element_by_css_selector("{滑块元素选择器}")
action = ActionChains(driver)
action.click_and_hold(slider).perform()
action.move_by_offset(move, 0).perform()
action.release().perform()
示例2:缺口滑块验证码
缺口滑块验证码相较于普通滑块验证码,多了一个缺口的概念。因此,需要先通过识别缺口位置,再计算前景图的偏移量。
同样可以通过 Chrome 的开发者工具获取到需要模拟登录的网站的登录界面,找到验证码对应的元素及其在页面中的位置:
<div class="gt_slider">
<div class="gt_slider_knob gt_show" style="left: -2px;">
<img src="{前景图url}">
</div>
<div class="gt_curtain gt_show" style="transform: translateX(0px);"></div>
<div class="gt_fullbg gt_show">
<img src="{完整背景图url}">
</div>
<div class="gt_bg gt_show">
<img src="{背景图url}">
<img src="{缺口图url}">
</div>
</div>
可见,完整背景图片为 "{完整背景图url}"
,背景图片中的缺口图为 "{缺口图url}"
,前景图为 "{前景图url}"
,前景图的初始位置在滑块元素的 style="left: -2px;"
中定义。
接下来需要通过 Python 下载并处理完整背景图片及其中的缺口图和前景图。同样使用 Pillow 库来处理图片。代码如下:
from PIL import Image
import requests
session = requests.Session()
# 获取完整背景图片及其位置信息
full_bg_url = "{完整背景图url}"
full_bg = session.get(full_bg_url).content
with open("full_bg.jpg", "wb") as f:
f.write(full_bg)
# 获取缺口图片及其位置信息
bg_url = "{缺口图url}"
bg_left = -115.231
bg_top = -40.3074
bg = session.get(bg_url).content
with open("bg.jpg", "wb") as f:
f.write(bg)
bg_img = Image.open("bg.jpg")
# 获取前景图及其位置信息
front_url = "{前景图url}"
front = session.get(front_url).content
with open("front.png", "wb") as f:
f.write(front)
front_img = Image.open("front.png")
_, top, _, bottom = driver.find_element(By.XPATH, "{滑块元素xpath}").get_attribute('style').split(';')
top, bottom = int(top.split(' ')[-1][:-2]), int(bottom.split(' ')[-1][:-2])
w, h = front_img.size
# 对比背景图片和前景图中的每个像素,找到相似度最高的位置
for x in range(w):
for y in range(h):
if front_img.getpixel((x, y)) != (0, 0, 0, 0):
bg_x = bg_left + x
bg_y = bg_top + y
bg_pixel = bg_img.getpixel((bg_x, bg_y))
if abs(bg_pixel[0]-front_img.getpixel((x,y))[0])<10 and abs(bg_pixel[1]-front_img.getpixel((x,y))[1]<10) and abs(bg_pixel[2]-front_img.getpixel((x,y))[2]<10):
left = x
break
# 计算偏移量
offset = left + top - 7
计算得到前景图的偏移量 offset
后,同样使用 Selenium 模拟鼠标拖动前景图即可:
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 模拟鼠标拖动前景图
driver = webdriver.Chrome()
driver.get("{登录页面url}")
# 点击滑块元素
slider = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "{滑块元素xpath}")))
slider.click()
# 拖动滑块
action = ActionChains(driver)
# 根据缺口位置计算鼠标移动轨迹
distance = 0
x_track = [i/10 for i in range(1, 11)]
for i in x_track:
distance += i + 2
# 按照轨迹拖动
action.click_and_hold(slider).perform()
for x in x_track[:7]:
action.move_by_offset(x, 1).perform()
for x in x_track[7:]:
action.move_by_offset(x, -1).perform()
action.release().perform()
总结
本文介绍了如何使用 Python 实现滑块验证码的识别和模拟操作,实现自动化登录功能。其中,普通滑块验证码只需要计算前景图的偏移量即可,而缺口滑块验证码需要先识别缺口位置,再计算偏移量。通过这种方法,我们可以大大提高登录效率和数据爬取的速度。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python 模拟网站登录——滑块验证码的识别 - Python技术站