selenium+cv2解决无原图的滑动验证码登陆

#欧模网滑动验证码登陆

     由于这个网站的滑动验证码没有原图,于是使用了cv2这个库的一些方法进行滑块和缺口位置的匹配,找到最相似的坐标然后进行移动,但是由于这些验证码的滑块图和验证码的图片有很多相似度高的地方,所以正确率不是很高,所以写了一个循环,失败了就重新获取图片并且再次尝试滑动,直到成功为止,这个库貌似是一个挺大的坑,没有深入的了解。这个滑动验证码似乎也没有滑动轨迹的要求,比较简单。这是刚入门的菜鸟写的代码,所以难免有些不太合理的地方,有错的地方请各位指教,一起学习提升。以下是全部代码,主要是做个笔记。


from PIL import Image
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.chrome.options import Options
import time
from urllib.parse import urljoin
import requests
import cv2
import numpy as np

class Captcha():
    def __init__(self):
        path = r"F:\chromedriver\chromedriver.exe"
        options = webdriver.ChromeOptions()
        options.add_argument("User-Agent = Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36")
        self.driver = webdriver.Chrome(executable_path=path,chrome_options=options)
        self.driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
            "source": """
                                                Object.defineProperty(navigator, 'webdriver', {
                                                    get: () => undefined
                                                });
                                            """
        })
        self.wait = WebDriverWait(self.driver,10)


    def login(self,url):
        self.driver.get(url)
        base_url = 'https://t.captcha.qq.com'
        account = self.wait.until(EC.presence_of_element_located((By.XPATH,"//*[@id='__layout']/div/div/div/div[2]/div/div[1]/div[2]/div[2]/div[1]/input")))
        account.send_keys("账号")
        time.sleep(0.2)
        password = self.wait.until(EC.presence_of_element_located((By.XPATH,"//*[@id='__layout']/div/div/div/div[2]/div/div[1]/div[2]/div[2]/div[2]/input")))
        password.send_keys("密码")
        time.sleep(0.2)
        login_button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME,"s-btn")))
        login_button.click()
        time.sleep(2)
        # 跳到iframe内
        self.driver.switch_to.frame("tcaptcha_iframe")


    def get_captcha(self):
        # 获取到两张图片链接
        bg_img_scr = self.wait.until(EC.presence_of_element_located(
            (By.XPATH, "//*[@id='slideBg']"))).get_attribute(
            'src')

        front_img_src = self.wait.until(EC.presence_of_element_located(
            (By.XPATH, "//*[@id='slideBlock']"))).get_attribute(
            'src')

        # 把图片下载到本地
        with open('./bg.jpg', mode='wb') as f:
            f.write(requests.get(bg_img_scr).content)
            # f.close()
        with open('./front.jpg', mode='wb') as f:
            f.write(requests.get(front_img_src).content)
            # f.close()


    def get_diff_captcha(self):
        # 读取图片
        bg = cv2.imread('./bg.jpg')
        front = cv2.imread('./front.jpg')
        # 灰度处理
        bg = cv2.cvtColor(bg, cv2.COLOR_BGR2GRAY)
        front = cv2.cvtColor(front, cv2.COLOR_BGR2GRAY)
        front = abs(255 - front)

        # 去掉滑块黑色部分
        front = front[front.any(1)]  # 0表示黑色,1表示高亮部分

        # 匹配->cv图像匹配算法
        result = cv2.matchTemplate(bg, front, cv2.TM_CCOEFF_NORMED) # match匹配,Template模板;精度高,速度慢的方法
        index_max = np.argmax(result)# 返回的是一维的位置,最大值索引
        # 反着推最大值的二维位置,和opencv是相反的
        x, y = np.unravel_index(index_max, result.shape)
        print("二维中坐标的位置:", x, y)
        return x,y


    def trace_and_move(self,x,y):
        drop = self.driver.find_element_by_xpath(
                        '//*[@id="slideBlock"]')
        ActionChains(self.driver).drag_and_drop_by_offset(drop, xoffset=(y-56)/2, yoffset=0).perform()
        time.sleep(2)


    def login_chk(self):
        k = 1
        while True:
            # 失败则重新获取图片再次识别,知道登陆成功可以获取下一个网页的内容位置
            self.get_captcha()
            x,y = self.get_diff_captcha()
            print("正在进行第%s次滑动验证" % k)
            self.trace_and_move(x,y)
            try:
                # 看是否能获取登陆成功后的网页内容
                success = self.driver.find_element_by_xpath(
                            '//*[@id="app"]/div[19]/div/img')
                if success:
                    success.click()
                    break
            except:
                print('第%s次验证失败...' % k, '\n')
                k = k + 1
            # 验证成功后获取“验证成功”,直到找到“验证成功”才跳出while True循环

    def main(self):
        # 模拟登陆目标网站,欧模网
        target_url = 'https://www.om.cn/login'
        self.login(target_url)
        self.login_chk()
        print("登陆成功")



if __name__ == '__main__':
    c = Captcha()
    c.main()
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值