您好,登錄后才能下訂單哦!
小編給大家分享一下python爬蟲中如何使用selenium+opencv識(shí)別滑動(dòng)驗(yàn)證并模擬登陸知乎功能,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
分別獲取驗(yàn)證碼背景圖和滑塊圖兩張照片,然后利用opencv庫,通過高斯模糊和Canny算法進(jìn)行處理,然后通過matchTemplate方法進(jìn)行兩張圖的匹配,獲得滑動(dòng)距離。需要注意的是,知乎驗(yàn)證碼在進(jìn)行操作的時(shí)候,需要在原有基礎(chǔ)上再向右偏移10px距離
def get_distance(self, bg_img_path='./bg.png', slider_img_path='./slider.png'): """獲取滑塊移動(dòng)距離""" # 背景圖片處理 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算法進(jìn)行邊緣檢測(cè) # 滑塊做同樣處理 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] # 橫坐標(biāo) return top_left
模擬人的行為,到缺口位置時(shí),繼續(xù)向后滑動(dòng)一段距離,然后再回退到準(zhǔn)確位置
def get_tracks(self, distance): '''滑動(dòng)軌跡 ''' tracks = [] v = 0 t = 0.2 # 單位時(shí)間 current = 0 # 滑塊當(dāng)前位移 distance += 10 # 多移動(dòng)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) # 單位時(shí)間(0.2s)的滑動(dòng)距離 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中的鼠標(biāo)動(dòng)作鏈,按照滑動(dòng)軌跡進(jìn)行滑動(dòng)
def mouse_move(self,slide,tracks): '''鼠標(biāo)滑動(dòng)''' #鼠標(biāo)點(diǎn)擊滑塊并按照不放 ActionChains(self.driver).click_and_hold(slide).perform() #按照軌跡進(jìn)行滑動(dòng), for track in tracks: ActionChains(self.driver).move_by_offset(track, 0).perform() ActionChains(self.driver).release(slide).perform()
使用selenium自動(dòng)化測(cè)試爬取知乎的時(shí)候出現(xiàn)了:錯(cuò)誤代碼10001:請(qǐng)求異常請(qǐng)升級(jí)客戶端后重新嘗試,這個(gè)錯(cuò)誤的產(chǎn)生是由于知乎可以檢測(cè)selenium自動(dòng)化測(cè)試的腳本
使用chrome的遠(yuǎn)程調(diào)試模式結(jié)合selenium來遙控操作chrome進(jìn)行抓取,這樣就會(huì)規(guī)避selenium被網(wǎng)站檢測(cè)到
將chrome.exe的目錄添加到系統(tǒng)環(huán)境變量,比如C:\Program Files\Google\Chrome\Application,這樣就可以直接在命令行輸入chrome.exe啟動(dòng)瀏覽器
打開cmd窗口,執(zhí)行命令
chrome.exe --remote-debugging-port=9222 --user-data-dir="E:\eliwang\selenium_data"
注意端口不要被占用,user-data-dir用來指明配置文件的路徑,自定義
此時(shí)會(huì)開啟瀏覽器,并打開一個(gè)新的標(biāo)簽頁
selenium接管的主要代碼
options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
1、使用瀏覽器對(duì)象的close()方法,quit()方法不行。
2、手動(dòng)打開,手動(dòng)關(guān)閉
完整登陸代碼
# coding:utf-8 import cv2 as cv import time import random from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait as WAIT from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By from urllib.request import urlretrieve class 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): '''執(zhí)行入口''' 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('賬號(hào)') 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() # 點(diǎn)擊登陸按鈕 time.sleep(1) #進(jìn)行滑動(dòng)驗(yàn)證,最多嘗試5次重新驗(yàn)證 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): '''滑動(dòng)驗(yàn)證''' 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') # 獲取驗(yàn)證碼背景圖url self.slider_img_url = self.wait.until(EC.presence_of_element_located((By.XPATH, '//img[@class="yidun_jigsaw"]'))).get_attribute('src') # 獲取驗(yàn)證碼滑塊圖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 # 實(shí)際移動(dòng)距離需要向右偏移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): '''鼠標(biāo)滑動(dòng)''' #鼠標(biāo)點(diǎn)擊滑塊并按照不放 ActionChains(self.driver).click_and_hold(slide).perform() #按照軌跡進(jìn)行滑動(dòng), 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'): """獲取滑塊移動(dòng)距離""" # 背景圖片處理 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算法進(jìn)行邊緣檢測(cè) # 滑塊做同樣處理 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] # 橫坐標(biāo) return top_left def get_tracks(self, distance): '''滑動(dòng)軌跡 ''' tracks = [] v = 0 t = 0.2 # 單位時(shí)間 current = 0 # 滑塊當(dāng)前位移 distance += 10 # 多移動(dòng)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) # 單位時(shí)間(0.2s)的滑動(dòng)距離 tracks.append(round(track)) # 加入軌跡 current += round(track) v = v0 + a * t #回退到大致位置 for i in range(5): tracks.append(-random.randint(1, 3)) return tracks if __name__ == '__main__': Zhihu_login().run()
看完了這篇文章,相信你對(duì)“python爬蟲中如何使用selenium+opencv識(shí)別滑動(dòng)驗(yàn)證并模擬登陸知乎功能”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。