本文主要是介绍滑动拼图验证码思路,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1. 最简单的的调用打码平台,收费
2. 还有一种利用华为云物体检测接口,可以自己上传图片去训练模型,模型训练好后,部署上线,就可以直接用了,收费,目测一次0.27元,也没细算,有提供接口服务,重要可以自己提供数据训练模型
3. 获取到一张完整的图片和带缺口的图片,利用PIL模块,对比两张图的像素点,计算出距离,然后selenium滑动,免费,比如:
以下代码为虎嗅 登陆
代码为18年7月的,已失效,只提供思路
# coding=utf-8
from selenium import webdriver
from selenium.webdriver.common.proxy import Proxy
from selenium.webdriver.common.proxy import ProxyType
from selenium.webdriver.support.wait import WebDriverWait
# from selenium.webdriver.support.ui import WebDriverWait
# from selenium.common.exceptions import NoAlertPresentException,TimeoutException,NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from PIL import ImageGrab, Image
import time, random, re, json, requests, os, sys
sys.path.append('C:/Users/Administrator/Desktop/tian_yan_cha/img_huxiu')class Hu_Xiu:def __init__(self):chromedriver = 'C:/Users/Administrator/AppData/Local/Programs/Python/Python35/Scripts/chromedriver'chromeOptions = webdriver.ChromeOptions()chromeOptions.add_argument("--proxy-server = http://115.198.32.22:6666")self.driver = webdriver.Chrome(chromedriver, chrome_options=chromeOptions) # chromedriver, chrome_options=chromeOptionsself.driver.maximize_window()# self.driver = webdriver.Firefox()self.header = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'}def visit_web(self):# 访问网站, 出现拼图按钮, 鼠标移动到拼图按钮上并执行, 刷新 极验 拼图print('----------- 访问网站 ----------')self.driver.get("https://www.huxiu.com/")time.sleep(random.uniform(10, 15))# 等待页面的上元素刷新出来 '''判断某个元素中是否可见并且是enable的,代表可点击''' 注册 按钮WebDriverWait(self.driver, 10, 0.5).until(EC.element_to_be_clickable((By.XPATH, '//*[@class="js-register"]')))reg_element = self.driver.find_element_by_xpath('//*[@class="js-register"]')reg_element.click()WebDriverWait(self.driver, 10, 0.5).until(EC.element_to_be_clickable((By.XPATH, '//div[@class="gt_slider_knob gt_show"]')))def visit_web_show(self):# 鼠标移动到拖动按钮,显示出拖动图片element = self.driver.find_element_by_xpath('//div[@class="gt_slider_knob gt_show"]')ActionChains(self.driver).move_to_element(element).perform()time.sleep(random.uniform(3, 5))# 刷新一下极验图片element = self.driver.find_element_by_xpath('//a[@class="gt_refresh_button"]')element.click()time.sleep(random.uniform(3, 5))# print(self.driver.page_source)def get_merge_img(self, image_name, location_list):# ---------》 重新合并 还原 图片 《----------print('---------》 重新合并 还原 图片 《----------')print(location_list)# 打开图片img = Image.open(image_name)# 创建新的图片,大小为260*116new_im = Image.new('RGB', (260, img.height))im_list_up = []im_list_down = []for location in location_list:# y值== -58 的图片属于上半部分,高度58if location['y'] == -58:im_list_up.append(img.crop((abs(location['x']), 58, abs(location['x']) + 10, img.height)))# 下边图片if location['y'] == 0:im_list_down.append(img.crop((abs(location['x']), 0, abs(location['x']) + 10, 58)))# 黏贴图片x_offset = 0for im in im_list_up:new_im.paste(im, (x_offset, 0))x_offset += im.size[0]x_offset = 0for im in im_list_down:new_im.paste(im, (x_offset, 58))x_offset += im.size[0]# new_im.show()return new_imdef get_img(self, xpath_rules):# 保存所有图片print('---------- 保存所有图片 ----------')images_list = self.driver.find_elements_by_xpath(xpath_rules)location_list = []for image_list in images_list:location = {}# 在html里面解析出小图片的url地址,还有长高的数值location['x'] = int(re.findall("background-image: url\(\"(.*?)\"\); background-position: (.*?)px (.*?)px;",image_list.get_attribute('style'))[0][1])location['y'] = int(re.findall("background-image: url\(\"(.*?)\"\); background-position: (.*?)px (.*?)px;",image_list.get_attribute('style'))[0][2])location_list.append(location)imageurl = re.findall("background-image: url\(\"(.*?)\"\); background-position: (.*?)px (.*?)px;",image_list.get_attribute('style'))[0][0]# 替换图片的后缀,获得图片的URLimage_url = imageurl.replace('webp', 'jpg')print(image_url)# 获取图片名字image_name = './img_huxiu/' + image_url.split('/')[-1]# 下载图片 保存res = requests.get(url=image_url, headers=self.header)with open(image_name, 'wb') as f:f.write(res.content)# ---------》 重新合并 还原 图片 《----------ima = self.get_merge_img(image_name, location_list)return ima, image_namedef is_similar_color(self, img1, img2, i, j):# 对比颜色 RGB值# 获取指定位置的RGB值# print('------------ 对比颜色 RGB值 -------------')pixel01 = img1.getpixel((i, j)) # 像素值 pixel01 -- (31, 160, 80)pixel02 = img2.getpixel((i, j)) # 像素值 pixel02 -- (31, 160, 80)# print('pixel01 -- ', pixel01)# print('pixel02 -- ', pixel02)for k in range(0, len(pixel01)):# 如果相差超过50则就认为找到了缺口的位置if abs(pixel01[k] - pixel02[k]) >= 30:return Falsereturn Truedef get_offset_destance(self, img1, img2):# 计算缺口距离# 两张原始图的大小都是相同的260*116# 那就通过两个for循环依次对比每个像素点的RGB值# 如果相差超过50则就认为找到了缺口的位置print('--------------- 计算缺口距离 --------------')for i in range(0, img1.width):for j in range(0, img1.height):# 判断颜色是否相近if self.is_similar_color(img1, img2, i, j) == False:img3 = img1.crop((i, j, i + 50, j + 40))img3.save('./img_huxiu/gap.jpg')print('=== 缺口距离 i == ', str(i))return idef get_track(self, loc):# 根据缺口的位置模拟x轴移动的轨迹print('--------------- 根据缺口的位置模拟x轴移动的轨迹 --------------')# 前 4/5 加速运动, 后 1/5 减速运动'''速度公式: v = v0 + at v0 初速度 a 加速度值 t 时间 v 末速度位移公式: s = v0*t + 1/2 * a*t*t '''v = 0 # 初速度t = 0.2 # 时间s0 = 0 # 当前的位移mid = 4/5*locprint('mid= %s' % mid)move_list = [] #其中一个元素 代表 在0.2s时间内的位移距离while s0 < loc:if s0 < mid:# 加速运动a = 2else:# 减速运动a = -4v0 = v# 0.2s 内的位移距离s = v0*t + 0.5*a*t*t# 当前位置s0 += s# print(s)# print('s0= ', s0)move_list.append(round(s))# 速度已经达到v,该速度作为下次的初速度v = v0 + a * tprint('s0= ', s0)print('move_list= %s' % move_list)# move_list= [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2]return move_listdef sliding(self, m_list):# 点击 滑动按钮 进行 滑动 验证print('--------------- 点击 滑动按钮 进行 滑动 验证 --------------')# 获取元素坐标elment = self.driver.find_element_by_xpath('//div[@class="gt_slider_knob gt_show"]')location = elment.locationprint('刷新按钮图片大小 = ', elment.size) # {'height': 44, 'width': 44}# 获取圆球高度y = location['y']print('y = ', y)# 点击元素不放ActionChains(self.driver).click_and_hold(on_element=elment).perform()time.sleep(random.uniform(0.2, 0.7))# 拖动元素track_string = ''for track in m_list:# xoffset=track+22:这里的移动位置的值是相对于滑动圆球左上角的相对值,而轨迹变量里的是圆球的中心点,所以要加上圆球长度的一半。# yoffset=y-445:这里也是一样的。不过要注意的是不同的浏览器渲染出来的结果是不一样的,要保证最终的计算后的值是22,也就是圆球高度的一半track_string = track_string + '(%s, %s)' % (track, y - 423)ActionChains(self.driver).move_to_element_with_offset(to_element=elment, xoffset=track + 22 , yoffset=y - 445).perform()time.sleep(random.uniform(0.03, 0.15))print('track_string = ', track_string)# xoffset=21,本质就是向后退一格。这里退了5格是因为圆球的位置和滑动条的左边缘有5格的距离p = 0while p < 5:ActionChains(self.driver).move_to_element_with_offset(to_element=elment, xoffset=21, yoffset=y - 445).perform()time.sleep(random.uniform(0.1, 0.7))p += 1# 释放鼠标ActionChains(self.driver).release(on_element=elment).perform()time.sleep(random.uniform(3, 5))def register(self):# 验证通过, 输入账号密码element = self.driver.find_element_by_xpath('//input[@id="sms_username"]')element.clear()element.send_keys("手机号")ele_captcha = self.driver.find_element_by_xpath('//span[@class="js-btn-captcha btn-captcha"]')ele_captcha.click()def all_steps(self):# 鼠标移动到拼图按钮上并执行, 刷新 极验 拼图self.visit_web_show()# 保存所有图片img1, img1_name = self.get_img('//div[@class="gt_cut_bg_slice"]')img2, img2_name = self.get_img('//div[@class="gt_cut_fullbg_slice"]')# print('img1 = %s ; img2 = %s' % (img1, img2))# 计算距离 x 轴移动距离loc = self.get_offset_destance(img1, img2) # 84os.remove(img1_name)os.remove(img2_name)# 生成 x 轴 移动轨迹# loc = 84move_list = self.get_track(loc)# 点击 滑动按钮 进行 滑动 验证self.sliding(move_list)def judge_succ(self):# 判断是否验证成功try:WebDriverWait(self.driver, 10, 0.5).until(EC.element_to_be_clickable((By.XPATH, '//div[@class="gt_ajax_tip gt_success"]')))print('>>>>>>>>>>>>>>>>>> 验证成功 <<<<<<<<<<<<<<<<<<<<<')return Trueexcept:print(">>>>>>>>>>>>>>>>>> 验证失败,点击刷新后重试 <<<<<<<<<<<<<<<<<<<<<")time.sleep(random.uniform(5, 10))return Falsedef run(self):# 访问网站, 出现拼图按钮,self.visit_web()# 步骤self.all_steps()# 判断 验证是否 成功, 不成功的话, 在从头 试一遍if self.judge_succ() == True:print('>>>>>>>>>>>>>>>>>> 验证成功 <<<<<<<<<<<<<<<<<<<<<')# 成功后输入手机号,发送验证码self.register()else:# 失败后递归执行拖动self.all_steps()if __name__ == '__main__':# 虎嗅网 爬虫hx = Hu_Xiu()hx.run()
这篇关于滑动拼图验证码思路的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!