分享

Python爬虫--------处理极验验证(滑块拼图验证)bilibili模式

 静幻堂 2019-12-26
有趣的程序媛 2019-12-24 14:40:37
from selenium import webdriverfrom PIL import Imageimport timeimport randomfrom selenium.webdriver import ActionChainsimport cv2from matplotlib import pyplot as pltclass slide():    #初始化    def __init__(self):        self.driver = webdriver.Chrome(executable_path='..') #自己的驱动地址        self.driver.maximize_window()        self.trance =0        self.driver.get("https://passport.bilibili.com/login")        self.driver.find_element_by_id('login-username').send_keys('....')#用户名        self.driver.find_element_by_id('login-passwd').send_keys('....')#密码        self.driver.find_element_by_class_name('btn-login').click()        print('login..........')        time.sleep(3)    #有完整背景图的网页截图    def before_deal_image(self):        self.js1 = 'document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="block"' #获得        self.driver.execute_script(self.js1)        time.sleep(2)        self.location = self.driver.find_element_by_class_name('geetest_widget').location        self.size = self.driver.find_element_by_class_name('geetest_widget').size        time.sleep(2)        self.driver.save_screenshot('capture1.png')  # 截取全屏        self.left = self.location['x'] + 220  # 后面的数字自己调节控制截图包含验证码图片        self.top = self.location['y'] + 57        self.right = self.location['x'] + self.size['width'] + 295        self.bottom = self.location['y'] + self.size['height'] + 113        # print(self.location, self.size)        self.im = Image.open('capture1.png')        self.im = self.im.crop((self.left, self.top, self.right, self.bottom))        self.im.save('ele_capture1.png')    # 滑块移动    def slide(self,num):        self.num=num        print('滑块应该移动距离------------->',self.num)        self.button = self.driver.find_element_by_class_name('geetest_slider_button')     #处理人机行为         first_distance = self.num/4*3        second_distance = self.num-first_distance-3        third_distance = self.num-second_distance-first_distance        ActionChains(self.driver).click_and_hold(self.button).move_by_offset(first_distance,random.random()).perform()        time.sleep(0.5)        ActionChains(self.driver).click_and_hold(self.button).move_by_offset(second_distance,random.random()).perform()        time.sleep(0.9)        ActionChains(self.driver).click_and_hold(self.button).move_by_offset(third_distance,random.random()).release().perform()         # 有缺口背景图的网页截图    def after_deal_image(self):        self.js2 = 'document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="none"'        self.driver.execute_script(self.js2)        self.driver.save_screenshot('capture2.png') #整张网页图        self.left = self.location['x'] + 220#与上面相同        self.top = self.location['y'] + 57        self.right = self.location['x'] + self.size['width'] + 295        self.bottom = self.location['y'] + self.size['height'] + 113        # print(self.location, self.size)        self.im = Image.open('capture2.png')        self.im = self.im.crop((self.left, self.top, self.right, self.bottom))        self.im.save('ele_capture2.png')  #元素切割图    #---------------------获得移动距离-----------------#    #获得滑动距离    def slide_distance(self,image1, image2):        cut_image = Image.open(image2)        full_image = Image.open(image1)        threshold = 86  # 边界值颜色都为85,85,85        for i in range(75, cut_image.size[0]):            for j in range(0, cut_image.size[1]):                pixel1 = cut_image.getpixel((i, j))                pixel2 = full_image.getpixel((i, j))                res_R = abs(pixel1[0] - pixel2[0])  # 计算RGB差                res_G = abs(pixel1[1] - pixel2[1])  # 计算RGB差                res_B = abs(pixel1[2] - pixel2[2])  # 计算RGB差                if res_R > threshold and res_G > threshold and res_B > threshold:                    print(i - 7)                    return i - 7    #-------------------------------------处理相似度问题--------------------------------#    # size=(256, 256)    def classify_gray_hist(self,image1, image2, size=(328, 211)): #截图大小        # 先计算直方图        # 几个参数必须用方括号括起来        # 这里直接用灰度图计算直方图,所以是使用第一个通道,        # 也可以进行通道分离后,得到多个通道的直方图        # bins 取为16        image1 = cv2.resize(image1, size)        image2 = cv2.resize(image2, size)        hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0]) #缺口背景图        hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0]) #完整背景图        # 可以比较下直方图        # plt.plot(range(256),hist1,'r')        # plt.plot(range(256),hist2,'b')        # plt.show()        # 计算直方图的重合度        degree = 0        for i in range(75,len(hist1)):            if hist1[i] != hist2[i]:                degree = degree + (1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))        else:            degree = degree + 1        degree = degree / len(hist1)        return degree    # -------------------------------------获得相似度-------------------------------#    def run0(self,image1, image2):        img1 = cv2.imread(image1)        # cv2.imshow('img1', img1)        img2 = cv2.imread(image2)        # cv2.imshow('img2', img2)        degree = self.classify_gray_hist(img1, img2)        print('两张图片相似度为。。。。。',int(100 * degree[0])) #这是完整背景图和验证码图的相似度        cv2.waitKey(0)        return int(degree[0] * 100)    # 函数的启动    def run(self):        try:            self.before_deal_image()            self.after_deal_image()            self.num = self.slide_distance('ele_capture1.png', 'ele_capture2.png')            print('原始距离--------->',self.num)            # 'ele_capture1.png', 'ele_capture2.png'            self.image1 = 'ele_capture1.png'            self.image2 = 'ele_capture2.png'            self.result = self.run0(self.image1, self.image2)            real_distance = self.num*(262/328) #这是实际截图大长度和验证码实际图片的的长度,自己更改            print('按照图像大小比列计算实际移动距离',real_distance)            self.slide(real_distance)            time.sleep(6)        except:            print('login_out..............')            time.sleep(7)        finally:            self.driver.quit()            print('程序运行结束')slide().run()
Python爬虫--------处理极验验证(滑块拼图验证)bilibili模式

透明度0 和1 的色差85,86左右徘徊,R,G,B三值都相等,均为左边的85,86,因此。阀值86,85均可,即上面函数的 threshold,主要的难点就是缺口位置的查找。故此需要一个函数来测试是否符合下面介绍。私信小编01 领取完整项目代码!

import cv2from PIL import Imagedef get_distance(cut_image, full_image):    cut_image = Image.open(cut_image) #缺口背景图    full_image = Image.open(full_image) #完整背景图    threshold = 86     #灰度值正好为86,86,86 这个是透明度的差值,边界值像素的RGB中的B值为准    for i in range(75, cut_image.size[0]):  #75为滑块的截图最右边阴影到图片最左端的长度        for j in range(0, cut_image.size[1]):            pixel1 = cut_image.getpixel((i, j))            pixel2 = full_image.getpixel((i, j))            res_R = abs(pixel1[0] - pixel2[0])  # 计算RGB差            res_G = abs(pixel1[1] - pixel2[1])  # 计算RGB差            res_B = abs(pixel1[2] - pixel2[2])  # 计算RGB差            if res_R > threshold and res_G > threshold and res_B > threshold:                print(i-7)                return i-7get_distance('ele_capture2.png','ele_capture1.png')#'ele_capture2.png','ele_capture1.png'(缺口背景图,完整背景图)

执行完第一个类,如果没登陆成功,就执行第上面这个,更改threshold ,并且将第一个类中的slide_distance()函数替换,上面函数中75均为为滑块的截图最右边阴影到图片最左端的长度,这个得自己修改。

还有另一个方法就是移动滑块进行截图,86的色差变小,然后移动距离变小,移动一次进行图片相似度处理,与背景完全图相似度90%之上后将移动的距离保留,进行行为处理,模拟人的移动方法,然后移动滑块,也可以成功,这需要图像算法,我是不会,但我找到资料后测试过,也能通过验证。慢,但是准确度100%。

如果都能成功,就可以将driver设置为无头模式,让selenium不在界面上显示。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多