python 爬虫 selenium滑块验证码(使用opencv识别滑块缺口位置,selenium自动化操作)

python 爬虫 selenium滑块验证码(使用opencv识别滑块缺口位置,selenium自动化操作)

原理:首先下载滑块的图片,使用opencv 计算到缺口的位置,然后再使用一个加速函数模拟手工操作的非匀速的运动,将滑块移动到缺口处,亲测该方法识别率 95% 左右

import cv2 as cv
import requests
from selenium import webdriver
# 导入鼠标事件类
from selenium.webdriver import ActionChains
import time
from selenium.webdriver.chrome import options
"""
pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
"""

class TencentSlider():
    # 计算到缺口的位置
    @staticmethod
    def get_pos(image):
        """
        缺口轮廓检测
        对付腾讯滑块够用
        该方法识别率 95% 左右
        """
        blurred = cv.GaussianBlur(image, (5, 5), 0)
        canny = cv.Canny(blurred, 200, 400)
        contours, hierarchy = cv.findContours(canny, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
        for i, contour in enumerate(contours):
            m = cv.moments(contour)
            if m['m00'] == 0:
                cx = cy = 0
            else:
                cx, cy = m['m10'] / m['m00'], m['m01'] / m['m00']
            if 6000 < cv.contourArea(contour) < 8000 and 370 < cv.arcLength(contour, True) < 390:
                if cx < 400:
                    continue
                x, y, w, h = cv.boundingRect(contour)  # 外接矩形
                cv.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
                # cv.imshow('image', image)   # 展示滑块的图片
                return x, y, w, h
        return 0

    # 加速度函数
    @staticmethod
    def get_tracks(distance):
        """
        拿到移动轨迹,模仿人的滑动行为,先匀加速后匀减速
        匀变速运动基本公式:
        ①v=v0+at
        ②s=v0t+½at²
        """
        # 初速度
        v = 0
        # 单位时间为0.3s来统计轨迹,轨迹即0.3内的位移
        t = 0.3
        # 位置/轨迹列表,列表内的一个元素代表0.3s的位移
        tracks = []
        # 当前的位移
        current = 0
        # 到达mid值开始减速
        mid = distance*4/5
        while current < distance:
            if current < mid:
                # 加速度越小,单位时间内的位移越小,模拟的轨迹就越多越详细
                a = 2
            else:
                a = -3

            # 初速度
            v0 = v
            # 0.3秒内的位移
            s = v0*t+0.5*a*(t**2)
            # 当前的位置
            current += s
            # 添加到轨迹列表
            tracks.append(round(s))
            # 速度已经达到v,该速度作为下次的初速度
            v = v0 + a*t
        return tracks
        # tracks: [第一个0.3秒的移动距离,第二个0.3秒的移动距离,...]

    # 初始化webdriver
    @property
    def get_browser(self):
        opt=options.Options()
        #opt.add_argument('--headless')
        #opt.add_argument('--incognito')
        opt.add_argument('--disable-infobars')
        #opt.add_argument('--user-agent="Mozilla/5.0 (Linux; Android 4.2.1; M040 Build/JOP40D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36"')
        opt.add_experimental_option('excludeSwitches', ['enable-automation'])
        browser = webdriver.Chrome(r'C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe', options=opt)
        return browser

    def parse_tencent(self):
        browser = self.get_browser
        browser.maximize_window()
        browser.get('https://007.qq.com/online.html')

        browser.find_elements_by_xpath('//div[@class="wp-onb-tit"]/a')[1].click()

        browser.find_element_by_xpath('//button[@id="code"]').click()
        time.sleep(5)

        #切换到新的iframe
        login_frame = browser.find_element_by_xpath('//iframe[@id="tcaptcha_iframe"]')
        browser.switch_to.frame(login_frame)#移动到iframe

        #下载图片
        src=browser.find_element_by_id('slideBg').get_attribute('src')
        print('图片链接:',src)
        img=requests.get(src).content
        with open('../test.jpg', 'wb')as f:
            f.write(img)

        img0 = cv.imread('../test.jpg')

        res=TencentSlider.get_pos(img0)
        distance=res[0]
        print('距离:',distance)
        cv.waitKey(0)
        cv.destroyAllWindows()

        element = browser.find_element_by_xpath('//div[@id="tcaptcha_drag_thumb"]')
        ActionChains(browser).click_and_hold(on_element=element).perform()
        #move_to_element_with_offset():移动到距离某个元素左上角多少距离的位置 distance[0]/2 - 25
        ActionChains(browser).move_to_element_with_offset(to_element=element,xoffset=220,yoffset=0).perform()

        # 6、使用加速度函数移动剩下的距离
        tracks = TencentSlider.get_tracks(25)
        for track in tracks:
            #开始移动 move_by_offset() 鼠标从当前位置移动多少距离
            ActionChains(browser).move_by_offset(xoffset=track,yoffset=0).perform()

        # 7、延迟释放鼠标: release()
        time.sleep(0.5)
        ActionChains(browser).release().perform()
        print('ok')

if __name__ == '__main__':
    slider = TencentSlider()
    slider.parse_tencent()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不走小道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值