from selenium.webdriver import ActionChains
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium import webdriver
from io import BytesIO
from PIL import Image
import random
import time
class CrackGesstest(object):
def __init__(self):
self.url = 'https://www.geetest.com/type/'
self.driver = webdriver.Chrome()
self.wait = WebDriverWait(self.driver, 10)
def __del__(self):
self.driver.close()
def openPage(self):
"""
打开页面,显示出滑动验证码
:return:
"""
# 打开页面
self.driver.get(self.url)
# 选择滑动行为验证
slide_button = self.wait.until(
EC.element_to_be_clickable((By.XPATH, '//div[@class="products-content"]//li[2]')))
slide_button.click()
# 点击验证按钮
verifi_button = self.wait.until(
EC.element_to_be_clickable((By.XPATH, '//div[@class="geetest_radar_tip"]')))
verifi_button.click()
def getImage(self, img_name):
"""
获得验证码图片
:param img_name: 图片名称.png
:return: image
"""
# 获得验证码图片
canvas = self.wait.until(
EC.presence_of_element_located((By.XPATH, '//canvas[@class="geetest_canvas_slice geetest_absolute"]')))
# 验证码位置
position = self.imagePosition(canvas)
# 屏幕截图
screenshot = self.driver.get_screenshot_as_png()
screenshot = Image.open(BytesIO(screenshot))
# 从屏幕截屏中截取验证码图片
image = screenshot.crop(position)
image.save(img_name)
print('图片保存完毕')
return image
def imagePosition(self, image_tag):
"""
获得图片的位置信息
:param image_tag:图片节点
:return: 位置元组(left, top, right, bottom)
"""
left = image_tag.location['x']
# 根据实际情况改变数据大小(否则截图位置可能与实际验证码所在位置不一样,具体为什么还不懂)
top = image_tag.location['y'] / 2
right = left + image_tag.size['width']
bottom = top + image_tag.size['height']
return (left, top, right, bottom)
def getDistante(self, img1, img2):
"""
获得图片不同之处,距离图片左边的距离
:param img1:残缺图片
:param img2:完整图片
:return: 距离
"""
# 大概比滑块长度大一点
distance = 60
for i in range(distance, img1.size[0]):
for j in range(1, img1.size[1]):
if not self.isPixelEqual(img1, img2, i, j):
distance = i
return distance
return distance
def isPixelEqual(self,img1, img2, i, j):
"""
判断两个像素点是否相同
:param img1:残缺图片
:param img2:完整图片
:param i: 像素横坐标
:param j: 像素纵坐标
:return: bool
"""
# 若某种颜色相差大于60,则认为不同
xxx = 65
rgb1 = img1.load()[i, j]
rgb2 = img2.load()[i, j]
if abs(rgb1[0] - rgb2[0]) < xxx and abs(rgb1[1] - rgb2[1]) < xxx and abs(rgb1[2] - rgb2[2]) < xxx:
return True
return False
def getTracks(self, distance):
"""
根据滑动距离设计滑动行为,避免被机器识别
:param distance:滑块应该滑动的距离
:return:forward_tracks(前向滑动距离),back_tracks(后向滑动距离)
"""
# 初始位置
x = 0
# 初始速度
v = 0
# 每次滑动时间t
t = [0.2, 0.1]
# 前向滑动行为
forward_tracks = []
# 后项滑动行为,根据实际可进行更改
back_tracks = [-6, -3, 2, 2, -3, -2, -2]
# 取前五分之三进行加速,后面减速
mid = distance * 3 / 5
while x < distance + 5:
if x < mid:
a = 2
else:
a = -3
i = random.randint(0, 1)
# 每次滑动距离
s = v * t[i] + 0.5 * a * t[i] * t[i]
# 更新速度v
v = v + a * t[i]
# 更新当前位置
x += s
# 更新前向滑动行为
forward_tracks.append(round(s))
return forward_tracks, back_tracks
def moveToGap(self, forward_tracks, back_tracks):
"""
根据滑动行为,移动滑块到残缺地方
:param forward_tracks: 前向滑动行为
:param back_tracks: 后向滑动行为
:return:
"""
# 模拟鼠标点击住滑块
button = self.wait.until(EC.presence_of_element_located((By.XPATH, '//div[@class="geetest_slider_button"]')))
ActionChains(self.driver).click_and_hold(button).perform()
# 拖动滑块
for track in forward_tracks:
ActionChains(self.driver).move_by_offset(xoffset=track, yoffset=0).perform()
time.sleep(0.1)
for back_track in back_tracks:
ActionChains(self.driver).move_by_offset(xoffset=back_track, yoffset=0).perform()
time.sleep(0.2)
# 释放鼠标
ActionChains(self.driver).release().perform()
def crackStart(self):
"""
进行破解验证码
:return:
"""
self.openPage()
# 获得残缺验证码图片
time.sleep(3)
img_name = '1bg.png'
bg_image = self.getImage(img_name)
# 获得完成验证码图片
self.driver.execute_script('document.querySelectorAll("canvas")[2].style=""')
time.sleep(2)
img_name = '1fullbg.png'
fullbg_image = self.getImage(img_name)
# 获取距离
distance = self.getDistante(bg_image, fullbg_image)
print('distance:', distance)
# 获取滑动行为
forward_tracks, back_tracks = self.getTracks(distance)
print(forward_tracks)
print(back_tracks)
# 移动滑块
self.moveToGap(forward_tracks, back_tracks)
time.sleep(10)
def main():
crack = CrackGesstest()
crack.crackStart()
print('work done!')
if __name__ == '__main__':
main()
破解滑动验证码(极验)
猜你喜欢
转载自blog.csdn.net/qq_29666899/article/details/83929983
今日推荐
周排行