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 = 0t = 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()returnprint('第%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')# 获取验证码背景图urlself.slider_img_url = self.wait.until(EC.presence_of_element_located((By.XPATH, '//img[@class="yidun_jigsaw"]'))).get_attribute('src')# 获取验证码滑块图urlurlretrieve(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# 实际移动距离需要向右偏移10pxtracks = 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 Falseelse:return Truedef 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_leftdef get_tracks(self, distance):'''滑动轨迹 '''tracks = []v = 0t = 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识别滑动验证并模拟登陆知乎功能】到此这篇关于python爬虫之利用selenium+opencv识别滑动验证并模拟登陆知乎的文章就介绍到这了,更多相关selenium+opencv滑动验证内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- PMSJ寻平面设计师之现代(Hyundai)
- 太平之莲
- 闲杂“细雨”
- 七年之痒之后
- 深入理解Go之generate
- 由浅入深理解AOP
- 期刊|期刊 | 国内核心期刊之(北大核心)
- 生活随笔|好天气下的意外之喜
- 感恩之旅第75天
- python学习之|python学习之 实现QQ自动发送消息