python-selenium-how-to-geetest-slide
1.前言
请准备好:
- 1.python 3.X 环境
- 2.安装好selenium 包
- 3.下载好对应浏览器驱动
- 3.极验证滑块验证网站:https://www.geetest.com/demo/slide-custom.html
2.流程逻辑
st=>start: 访问网页
op1=>operation: 点击验证
op2=>operation: 获取滑块图片
op3=>operation: 计算位移
op4=>operation: 模拟人工滑动
cond=>condition: 验证成功 Yes or No?
e=>end: 完成任务
st->op1->op2->op3->op4->cond
cond(yes)->e
cond(no)->op2
3.具体程序
3.1获取图片
一张为原图,另一张为有滑块的图
不含滑块原图
含滑块图片
def get_image(browser, wait):
"""
获取图片截图
bg.png==>原始图片
fullbg.png==>无滑块图片
"""
button = wait.until(
EC.presence_of_element_located(
(By.XPATH,
'/html/body/form/div[3]/div/div[3]/div[2]/div[1]/div[3]')))
button.click()
geetest_canvas_bg = wait.until(
EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_bg')))
time.sleep(0.5)
js = 'var change = document.getElementsByClassName("geetest_canvas_slice");change[0].style = "display: none;"'
browser.execute_script(js)
geetest_canvas_bg.screenshot('bg.png')
js = 'var change1 = document.getElementsByClassName("geetest_canvas_fullbg");change1[0].style = "display: block;"'
browser.execute_script(js)
time.sleep(0.5)
geetest_canvas_fullbg = wait.until(
EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_bg')))
geetest_canvas_fullbg.screenshot('fullbg.png')
image_bg = Image.open('bg.png')
image_fullbg = Image.open('fullbg.png')
js = 'var change = document.getElementsByClassName("geetest_canvas_slice");change[0].style = "display: block;"'
browser.execute_script(js)
return image_bg, image_fullbg
browser.execute_script()注入js,让滑块消失
3.2比较图片,计算位移
方法一:
def get_diff_location(image1, image2):
'''
通过像素对比 找到缺口位置
:param image1:
:param image2:
:return:
'''
for x in range(60, image1.size[0]):
for y in range(1, image2.size[1]):
if is_similar(image1, image2, x, y) == False:
# 判断成立 表示xy这个点 两张图的像素点是不一样的
return x
def is_similar(image1, image2, x, y):
'''
找两个像素点不同之处
'''
pixel1 = image1.getpixel((x, y))
pixel2 = image2.getpixel((x, y)) # 元组
for i in range(0, 3):
if abs(pixel1[i] - pixel2[i]) >= 50:
return False
return True
方法二:
def get_gap(image1, image2):
"""
获取缺口偏移量
:param image1: 带缺口图片
:param image2: 不带缺口图片
:return:
"""
left = 60
print(image1.size[0])
print(image1.size[1])
for i in range(left, image1.size[0]):
for j in range(image1.size[1]):
if not is_pixel_equal(image1, image2, i, j):
left = i
return left
return left
def is_pixel_equal(image1, image2, x, y):
"""
判断两个像素是否相同
:param image1: 图片1
:param image2: 图片2
:param x: 位置x
:param y: 位置y
:return: 像素是否相同
"""
# 取两个图片的像素点
pixel1 = image1.load()[x, y]
pixel2 = image2.load()[x, y]
threshold = 60
if abs(pixel1[0] - pixel2[0]) < threshold and abs(
pixel1[1] - pixel2[1]) < threshold and abs(pixel1[2] -
pixel2[2]) < threshold:
return True
else:
return False
3.3模拟人工滑动
我的思路:快速滑动(20),慢慢滑动略微超过(10-5),慢慢返回(-1)
def get_tracks(x: int):
tracks = [0, 0]
num = 0
while num + 20 < x:
num += 20
tracks.append(20)
while num + 10 < x:
num += 10
tracks.append(10)
while num + 5 < x:
num += 5
tracks.append(5)
while num + 3 < x:
num += 3
tracks.append(3)
for i in range((x - num) + 2):
tracks.append(1)
tracks.append(-1)
tracks.append(-1)
return tracks
注意:由于滑块有初始位移,计算时要根据情况减去
3.4主程序
def Geetest(url, path):
browser = webdriver.Firefox(executable_path=path)
browser.maximize_window()
browser.get(url)
wait = WebDriverWait(browser, 10)
image_bg, image_fullbg = get_image(browser, wait)
x = get_diff_location(image_bg, image_fullbg)
print('偏移距离:' + str(x))
tracks = get_tracks(x - 5)
elem = wait.until(
EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button')))
ActionChains(browser).click_and_hold(elem).perform()
for track in tracks:
ActionChains(browser).move_by_offset(xoffset=track,
yoffset=0).perform()
time.sleep(1)
ActionChains(browser).release(elem).perform()
4.完整程序&&成果
from os import path
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
import time
from PIL import Image
def get_image(browser, wait):
"""
获取图片截图
bg.png==>原始图片
fullbg.png==>无滑块图片
"""
button = wait.until(
EC.presence_of_element_located(
(By.XPATH,
'/html/body/form/div[3]/div/div[3]/div[2]/div[1]/div[3]')))
button.click()
geetest_canvas_bg = wait.until(
EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_bg')))
time.sleep(0.5)
js = 'var change = document.getElementsByClassName("geetest_canvas_slice");change[0].style = "display: none;"'
browser.execute_script(js)
geetest_canvas_bg.screenshot('bg.png')
js = 'var change1 = document.getElementsByClassName("geetest_canvas_fullbg");change1[0].style = "display: block;"'
browser.execute_script(js)
time.sleep(0.5)
geetest_canvas_fullbg = wait.until(
EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_bg')))
geetest_canvas_fullbg.screenshot('fullbg.png')
image_bg = Image.open('bg.png')
image_fullbg = Image.open('fullbg.png')
js = 'var change = document.getElementsByClassName("geetest_canvas_slice");change[0].style = "display: block;"'
browser.execute_script(js)
return image_bg, image_fullbg
def get_diff_location(image1, image2):
'''
通过像素对比 找到缺口位置
:param image1:
:param image2:
:return:
'''
for x in range(60, image1.size[0]):
for y in range(1, image2.size[1]):
if is_similar(image1, image2, x, y) == False:
# 判断成立 表示xy这个点 两张图的像素点是不一样的
return x
def is_similar(image1, image2, x, y):
'''
找两个像素点不同之处
'''
pixel1 = image1.getpixel((x, y))
pixel2 = image2.getpixel((x, y)) # 元组
for i in range(0, 3):
if abs(pixel1[i] - pixel2[i]) >= 50:
return False
return True
def get_tracks(x: int):
tracks = [0, 0]
num = 0
while num + 20 < x:
num += 20
tracks.append(20)
while num + 10 < x:
num += 10
tracks.append(10)
while num + 5 < x:
num += 5
tracks.append(5)
while num + 3 < x:
num += 3
tracks.append(3)
for i in range((x - num) + 2):
tracks.append(1)
tracks.append(-1)
tracks.append(-1)
return tracks
def get_gap(image1, image2):
"""
获取缺口偏移量
:param image1: 带缺口图片
:param image2: 不带缺口图片
:return:
"""
left = 60
print(image1.size[0])
print(image1.size[1])
for i in range(left, image1.size[0]):
for j in range(image1.size[1]):
if not is_pixel_equal(image1, image2, i, j):
left = i
return left
return left
def is_pixel_equal(image1, image2, x, y):
"""
判断两个像素是否相同
:param image1: 图片1
:param image2: 图片2
:param x: 位置x
:param y: 位置y
:return: 像素是否相同
"""
# 取两个图片的像素点
pixel1 = image1.load()[x, y]
pixel2 = image2.load()[x, y]
threshold = 60
if abs(pixel1[0] - pixel2[0]) < threshold and abs(
pixel1[1] - pixel2[1]) < threshold and abs(pixel1[2] -
pixel2[2]) < threshold:
return True
else:
return False
def Geetest(url, path):
browser = webdriver.Firefox(executable_path=path)
browser.maximize_window()
browser.get(url)
wait = WebDriverWait(browser, 10)
image_bg, image_fullbg = get_image(browser, wait)
x = get_diff_location(image_bg, image_fullbg)
print('偏移距离:' + str(x))
tracks = get_tracks(x - 5)
elem = wait.until(
EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button')))
ActionChains(browser).click_and_hold(elem).perform()
for track in tracks:
ActionChains(browser).move_by_offset(xoffset=track,
yoffset=0).perform()
time.sleep(1)
ActionChains(browser).release(elem).perform()
if __name__ == '__main__':
path = '/Volumes/数据/program/python/spider/geckodriver'
url = 'https://www.geetest.com/demo/slide-custom.html'
Geetest(url, path)
5.参考
最后修改: 2022-08-04T17:22:02
版权声明:署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
comment 评论
好啊