千家信息网

python爬虫中如何使用selenium+opencv识别滑动验证并模拟登陆知乎功能

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,小编给大家分享一下python爬虫中如何使用selenium+opencv识别滑动验证并模拟登陆知乎功能,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!滑动验证距离分别获取验证码背景图
千家信息网最后更新 2025年01月23日python爬虫中如何使用selenium+opencv识别滑动验证并模拟登陆知乎功能

小编给大家分享一下python爬虫中如何使用selenium+opencv识别滑动验证并模拟登陆知乎功能,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

滑动验证距离

分别获取验证码背景图和滑块图两张照片,然后利用opencv库,通过高斯模糊和Canny算法进行处理,然后通过matchTemplate方法进行两张图的匹配,获得滑动距离。需要注意的是,知乎验证码在进行操作的时候,需要在原有基础上再向右偏移10px距离

def get_distance(self, bg_img_path='./bg.png', slider_img_path='./slider.png'):        """获取滑块移动距离"""        # 背景图片处理        bg_img = cv.imread(bg_img_path, 0)  # 读入灰度图片        bg_img = cv.GaussianBlur(bg_img, (3, 3), 0)  # 高斯模糊去噪        bg_img = cv.Canny(bg_img, 50, 150)  # Canny算法进行边缘检测        # 滑块做同样处理        slider_img = cv.imread(slider_img_path, 0)        slider_img = cv.GaussianBlur(slider_img, (3, 3), 0)        slider_img = cv.Canny(slider_img, 50, 150)        # 寻找最佳匹配        res = cv.matchTemplate(bg_img, slider_img, cv.TM_CCOEFF_NORMED)        # 最小值,最大值,并得到最小值, 最大值的索引        min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)        # 例如:(-0.05772797390818596, 0.30968162417411804, (0, 0), (196, 1))        top_left = max_loc[0]  # 横坐标        return top_left

滑块运动轨迹

模拟人的行为,到缺口位置时,继续向后滑动一段距离,然后再回退到准确位置

def get_tracks(self, distance):        '''滑动轨迹 '''        tracks = []        v = 0        t = 0.2  # 单位时间        current = 0  # 滑块当前位移        distance += 10  # 多移动10px,然后回退        while current < distance:            if current < distance * 5 / 8:                a = random.randint(1, 3)            else:                a = -random.randint(2, 4)            v0 = v  # 初速度            track = v0 * t + 0.5 * a * (t ** 2)  # 单位时间(0.2s)的滑动距离            tracks.append(round(track))  # 加入轨迹            current += round(track)            v = v0 + a * t        #回退到大致位置        for i in range(5):            tracks.append(-random.randint(1, 3))        return tracks

鼠标滑动操作

通过selenium中的鼠标动作链,按照滑动轨迹进行滑动

def mouse_move(self,slide,tracks):        '''鼠标滑动'''        #鼠标点击滑块并按照不放        ActionChains(self.driver).click_and_hold(slide).perform()        #按照轨迹进行滑动,        for track in tracks:            ActionChains(self.driver).move_by_offset(track, 0).perform()         ActionChains(self.driver).release(slide).perform()

规避知乎selenium检测

使用selenium自动化测试爬取知乎的时候出现了:错误代码10001:请求异常请升级客户端后重新尝试,这个错误的产生是由于知乎可以检测selenium自动化测试的脚本

使用chrome的远程调试模式结合selenium来遥控操作chrome进行抓取,这样就会规避selenium被网站检测到

添加环境变量

将chrome.exe的目录添加到系统环境变量,比如C:\Program Files\Google\Chrome\Application,这样就可以直接在命令行输入chrome.exe启动浏览器

打开cmd窗口,执行命令

chrome.exe --remote-debugging-port=9222 --user-data-dir="E:\eliwang\selenium_data"

注意端口不要被占用,user-data-dir用来指明配置文件的路径,自定义

此时会开启浏览器,并打开一个新的标签页

selenium接管的主要代码

options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")

关闭浏览器窗口

1、使用浏览器对象的close()方法,quit()方法不行。

2、手动打开,手动关闭

完整登陆代码

# coding:utf-8import cv2 as cvimport timeimport randomfrom selenium import webdriverfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.ui import WebDriverWait as WAITfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.common.by import Byfrom urllib.request import urlretrieveclass Zhihu_login:    '''知乎模拟登陆'''    def __init__(self):        options = webdriver.ChromeOptions()        #操控chrome浏览器        options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")        self.driver = webdriver.Chrome(options=options)        self.wait = WAIT(self.driver, 5)        self.url = 'https://www.zhihu.com/'        self.bg_img_path = './bg.png'        self.slider_img_path = './slider.png'    def run(self):        '''执行入口'''        self.driver.get(self.url)        try:            if WAIT(self.driver,3).until(EC.presence_of_element_located((By.ID,'Popover15-toggle'))):                print('登陆成功')                self.save_cookie()                self.driver.close()        except:            # 切换到密码登陆            self.wait.until(EC.element_to_be_clickable((By.XPATH, '//div[contains(@class,"SignFlow-tabs")]/div[2]'))).click()            name_input = self.driver.find_element_by_name('username')            name_input.clear()            name_input.send_keys('账号')            pass_input = self.driver.find_element_by_name('password')            pass_input.clear()            pass_input.send_keys('密码')            self.wait.until(EC.element_to_be_clickable((By.XPATH, '//button[@type="submit"]'))).click()  # 点击登陆按钮            time.sleep(1)            #进行滑动验证,最多尝试5次重新验证            if self.slide_verify():                print('登陆成功')                self.save_cookie()                self.driver.close()            else:                print('第1次登陆失败')                for i in range(4):                    print('正在尝试第%d次登陆'%(i+2))                    if self.slide_verify():                        print('第%d次登陆成功'%(i+2))                        self.save_cookie()                        self.driver.close()                        return                    print('第%d次登陆失败' % (i + 2))                print('登陆失败5次,停止登陆')                self.driver.close()    def slide_verify(self):        '''滑动验证'''        slider_button = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//div[@class="yidun_slider"]')))        self.bg_img_url = self.wait.until(EC.presence_of_element_located((By.XPATH, '//img[@class="yidun_bg-img"]'))).get_attribute('src')  # 获取验证码背景图url        self.slider_img_url = self.wait.until(EC.presence_of_element_located((By.XPATH, '//img[@class="yidun_jigsaw"]'))).get_attribute('src')  # 获取验证码滑块图url        urlretrieve(self.bg_img_url, self.bg_img_path)        urlretrieve(self.slider_img_url, self.slider_img_path)        distance = self.get_distance(self.bg_img_path, self.slider_img_path)        distance += 10  # 实际移动距离需要向右偏移10px        tracks = self.get_tracks(distance)        self.mouse_move(slider_button,tracks)        try:            element = self.wait.until(EC.presence_of_element_located((By.ID,'Popover15-toggle')))        except:            return False        else:            return True    def save_cookie(self):        cookie = {}        for item in self.driver.get_cookies():            cookie[item['name']] = item['value']        print(cookie)        print('成功获取登陆知乎后的cookie信息')    def mouse_move(self,slide,tracks):        '''鼠标滑动'''        #鼠标点击滑块并按照不放        ActionChains(self.driver).click_and_hold(slide).perform()        #按照轨迹进行滑动,        for track in tracks:            ActionChains(self.driver).move_by_offset(track, 0).perform()        ActionChains(self.driver).release(slide).perform()    def get_distance(self, bg_img_path='./bg.png', slider_img_path='./slider.png'):        """获取滑块移动距离"""        # 背景图片处理        bg_img = cv.imread(bg_img_path, 0)  # 读入灰度图片        bg_img = cv.GaussianBlur(bg_img, (3, 3), 0)  # 高斯模糊去噪        bg_img = cv.Canny(bg_img, 50, 150)  # Canny算法进行边缘检测        # 滑块做同样处理        slider_img = cv.imread(slider_img_path, 0)        slider_img = cv.GaussianBlur(slider_img, (3, 3), 0)        slider_img = cv.Canny(slider_img, 50, 150)        # 寻找最佳匹配        res = cv.matchTemplate(bg_img, slider_img, cv.TM_CCOEFF_NORMED)        # 最小值,最大值,并得到最小值, 最大值的索引        min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)        # 例如:(-0.05772797390818596, 0.30968162417411804, (0, 0), (196, 1))        top_left = max_loc[0]  # 横坐标        return top_left    def get_tracks(self, distance):        '''滑动轨迹 '''        tracks = []        v = 0        t = 0.2  # 单位时间        current = 0  # 滑块当前位移        distance += 10  # 多移动10px,然后回退        while current < distance:            if current < distance * 5 / 8:                a = random.randint(1, 3)            else:                a = -random.randint(2, 4)            v0 = v  # 初速度            track = v0 * t + 0.5 * a * (t ** 2)  # 单位时间(0.2s)的滑动距离            tracks.append(round(track))  # 加入轨迹            current += round(track)            v = v0 + a * t        #回退到大致位置        for i in range(5):            tracks.append(-random.randint(1, 3))        return tracksif __name__ == '__main__':    Zhihu_login().run()

看完了这篇文章,相信你对"python爬虫中如何使用selenium+opencv识别滑动验证并模拟登陆知乎功能"有了一定的了解,如果想了解更多相关知识,欢迎关注行业资讯频道,感谢各位的阅读!

0