企業(yè)網(wǎng)站策劃運(yùn)營(yíng)推廣
因?yàn)榉N種原因沒能實(shí)現(xiàn)愿景的目標(biāo),在這里記錄一下中間結(jié)果,也算是一個(gè)收?qǐng)霭?。這篇文章主要是用selenium解決滑塊驗(yàn)證碼的個(gè)別案列。
思路:
用selenium打開瀏覽器指定網(wǎng)站
將殘缺塊圖片和背景圖片下載到本地
對(duì)比兩張圖片的相似地方,計(jì)算要滑動(dòng)的距離
規(guī)劃路線,移動(dòng)滑塊
一、實(shí)現(xiàn)步驟
1、用selenium打開瀏覽器瀏覽指定網(wǎng)站
1、找到chromedriver.exe的路徑
點(diǎn)擊開始找到谷歌圖標(biāo)==》右鍵更多==》打開文件位置==》右鍵谷歌快捷方式==》屬性 ==》打開文件所在的位置 ==》復(fù)制路徑
2、代碼
from selenium import webdriver# chrome_path要改成你自己的路徑chrome_path = r"C:\Users\11248\AppData\Local\Google\Chrome\Application\chromedriver.exe"url = 'https://icas.jnu.edu.cn/cas/login'driver = webdriver.Chrome(chrome_path)driver.get(url)
二、將殘缺塊圖片和背景圖片下載到本地
1、找到圖片位置
打開網(wǎng)頁進(jìn)入開發(fā)者工具,找到圖片位置
2、代碼
import timeimport requestsfrom PIL import Imagefrom selenium.webdriver.common.by import Byfrom io import BytesIOtime.sleep(5)# 進(jìn)入頁面要停留幾秒鐘,等頁面加載完target_link = driver.find_element(By.CLASS_NAME, "yidun_bg-img").get_attribute('src')template_link = driver.find_element(By.CLASS_NAME, "yidun_jigsaw").get_attribute('src')target_img = Image.open(BytesIO(requests.get(target_link).content))template_img = Image.open(BytesIO(requests.get(template_link).content))target_img.save('target.jpg')template_img.save('template.png')
三、對(duì)比兩張圖片的相似地方,計(jì)算要滑動(dòng)的距離
1、用matchTemplate獲取移動(dòng)距離
因?yàn)楸尘皥D片中的殘缺塊位置和原始?xì)埲眻D的亮度有所差異,直接對(duì)比兩張圖片相似的地方,往往得不到令人滿意的結(jié)果,在此要對(duì)兩張圖片進(jìn)行一定的處理,為了避免這種亮度的干擾,筆者這里將兩張圖片先進(jìn)行灰度處理,再對(duì)圖像進(jìn)行高斯處理,最后進(jìn)行邊緣檢測(cè)。
def handel_img(img):imgGray = cv2.cvtColor(img, cv2.COLOR_RGBA2GRAY) # 轉(zhuǎn)灰度圖imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1) # 高斯模糊imgCanny = cv2.Canny(imgBlur, 60, 60) # Canny算子邊緣檢測(cè)return imgCanny
?將JPG圖像轉(zhuǎn)變?yōu)?通道(RGBA)
def add_alpha_channel(img):""" 為jpg圖像添加alpha通道 """r_channel, g_channel, b_channel = cv2.split(img) # 剝離jpg圖像通道alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255 # 創(chuàng)建Alpha通道img_new = cv2.merge((r_channel, g_channel, b_channel, alpha_channel)) # 融合通道return img_new
2、代碼
import cv2# 讀取圖像def match(img_jpg_path, img_png_path):# 讀取圖像img_jpg = cv2.imread(img_jpg_path, cv2.IMREAD_UNCHANGED)img_png = cv2.imread(img_png_path, cv2.IMREAD_UNCHANGED)# 判斷jpg圖像是否已經(jīng)為4通道if img_jpg.shape[2] == 3:img_jpg = add_alpha_channel(img_jpg)img = handel_img(img_jpg)small_img = handel_img(img_png)res_TM_CCOEFF_NORMED = cv2.matchTemplate(img, small_img, 3)value = cv2.minMaxLoc(res_TM_CCOEFF_NORMED)value = value[3][0] # 獲取到移動(dòng)距離return value
3、檢驗(yàn)效果
為了驗(yàn)證思路和方法是否得當(dāng),這里將滑塊圖片與背景圖片進(jìn)行拼接,為后面埋下一個(gè)小坑。
def merge_img(jpg_img, png_img, y1, y2, x1, x2):""" 將png透明圖像與jpg圖像疊加y1,y2,x1,x2為疊加位置坐標(biāo)值"""# 判斷jpg圖像是否已經(jīng)為4通道if jpg_img.shape[2] == 3:jpg_img = add_alpha_channel(jpg_img)# 獲取要覆蓋圖像的alpha值,將像素值除以255,使值保持在0-1之間alpha_png = png_img[yy1:yy2, xx1:xx2, 3] / 255.0alpha_jpg = 1 - alpha_png# 開始疊加for c in range(0, 3):jpg_img[y1:y2, x1:x2, c] = ((alpha_jpg * jpg_img[y1:y2, x1:x2, c]) + (alpha_png * png_img[yy1:yy2, xx1:xx2, c]))return jpg_imgimg_jpg_path = 'target.jpg' # 讀者可自行修改文件路徑img_png_path = 'template.png' # 讀者可自行修改文件路徑x1 = match(img_jpg_path, img_png_path)y1 = 0x2 = x1 + img_png.shape[1]y2 = y1 + img_png.shape[0]# 開始疊加res_img = merge_img(img_jpg, img_png, y1, y2, x1, x2)cv2.imshow("res_img ", res_img)cv2.waitKey(0)
四、規(guī)劃路線,移動(dòng)滑塊
1、點(diǎn)擊滑塊移動(dòng)
用第3節(jié)已經(jīng)獲取到的距離,點(diǎn)擊滑塊進(jìn)行移動(dòng)
from selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWaitfrom selenium.webdriver import ActionChainsdef crack_slider(distance):wait = WebDriverWait(driver, 20)slider = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'yidun_slider')))ActionChains(self.driver).click_and_hold(slider).perform()ActionChains(self.driver).move_by_offset(xoffset=distance, yoffset=0).perform()time.sleep(2)ActionChains(self.driver).release().perform()return 0
神奇的事情是,坑來了,沒有匹配成功。
2、匹配失敗原因
這里有以下兩點(diǎn)原因:
-
圖片尺寸發(fā)生了變化,距離要進(jìn)行轉(zhuǎn)換。
-
滑塊滑動(dòng)時(shí),滑塊和殘缺塊的相對(duì)位置有變動(dòng)。
首先解決圖片尺寸變化問題,找到網(wǎng)頁中圖片大小:345x172.500
下載到本地圖片大小:480x240
所以要對(duì)距離進(jìn)行以下處理:
distance = distance / 480 * 345
關(guān)于第二個(gè)問題,這里沒有找到很好的測(cè)量工具測(cè)量出來,好在驗(yàn)證碼對(duì)位置精確度要求不高,就一個(gè)個(gè)試數(shù)吧。
distance = distance /480 * 345 + 12
五、補(bǔ)充
在對(duì)極驗(yàn)驗(yàn)證碼進(jìn)行學(xué)習(xí)中,有的網(wǎng)站對(duì)移動(dòng)軌跡進(jìn)行了驗(yàn)證,如果滑動(dòng)太快,也會(huì)被識(shí)別出機(jī)器操作,為了模擬人工操作,出色的程序員寫出了一個(gè)魔幻移動(dòng)軌跡
舉個(gè)例子:我們可以先超過目標(biāo),再往回移動(dòng)。
def get_tracks(distance):distance += 20v = 0t = 0.2forward_tracks = []current = 0mid = distance * 3 / 5while current < distance:if current < mid:a = 2else:a = -3s = v * t + 0.5 * a * (t ** 2)v = v + a * tcurrent += sforward_tracks.append(round(s))back_tracks = [-3, -3, -2, -2, -2, -2, -2, -1, -1, -1]return {'forward_tracks': forward_tracks, 'back_tracks': back_tracks}def crack_slider(tracks):wait = WebDriverWait(driver, 20)slider = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'yidun_slider')))ActionChains(driver).click_and_hold(slider).perform() # 模擬按住鼠標(biāo)左鍵for track in tracks['forward_tracks']:ActionChains(driver).move_by_offset(xoffset=track, yoffset=0).perform()time.sleep(0.5)for back_tracks in tracks['back_tracks']:ActionChains(driver).move_by_offset(xoffset=back_tracks, yoffset=0).perform()ActionChains(driver).move_by_offset(xoffset=-4, yoffset=0).perform()ActionChains(driver).move_by_offset(xoffset=4, yoffset=0).perform()time.sleep(0.5)ActionChains(driver).release().perform()# 釋放左鍵return 0
六、完整代碼
# coding=utf-8import reimport requestsimport timefrom io import BytesIOimport cv2import numpy as npfrom PIL import Imagefrom selenium import webdriverfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWaitclass CrackSlider():# 通過瀏覽器截圖,識(shí)別驗(yàn)證碼中缺口位置,獲取需要滑動(dòng)距離,并破解滑動(dòng)驗(yàn)證碼def __init__(self):super(CrackSlider, self).__init__()self.opts = webdriver.ChromeOptions()self.opts.add_experimental_option('excludeSwitches', ['enable-logging'])# self.driver = webdriver.Chrome(ChromeDriverManager().install(), options=self.opts)chrome_path = r"C:\Users\11248\AppData\Local\Google\Chrome\Application\chromedriver.exe"self.driver = webdriver.Chrome(chrome_path, options=self.opts)self.url = 'https://icas.jnu.edu.cn/cas/login'self.wait = WebDriverWait(self.driver, 10)def get_pic(self):self.driver.get(self.url)time.sleep(5)target_link = self.driver.find_element(By.CLASS_NAME, "yidun_bg-img").get_attribute('src')template_link = self.driver.find_element(By.CLASS_NAME, "yidun_jigsaw").get_attribute('src')target_img = Image.open(BytesIO(requests.get(target_link).content))template_img = Image.open(BytesIO(requests.get(template_link).content))target_img.save('target.jpg')template_img.save('template.png')def crack_slider(self, distance):slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'yidun_slider')))ActionChains(self.driver).click_and_hold(slider).perform()ActionChains(self.driver).move_by_offset(xoffset=distance, yoffset=0).perform()time.sleep(2)ActionChains(self.driver).release().perform()return 0def add_alpha_channel(img):""" 為jpg圖像添加alpha通道 """r_channel, g_channel, b_channel = cv2.split(img) # 剝離jpg圖像通道alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255 # 創(chuàng)建Alpha通道img_new = cv2.merge((r_channel, g_channel, b_channel, alpha_channel)) # 融合通道return img_newdef handel_img(img):imgGray = cv2.cvtColor(img, cv2.COLOR_RGBA2GRAY) # 轉(zhuǎn)灰度圖imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1) # 高斯模糊imgCanny = cv2.Canny(imgBlur, 60, 60) # Canny算子邊緣檢測(cè)return imgCannydef match(img_jpg_path, img_png_path):# 讀取圖像img_jpg = cv2.imread(img_jpg_path, cv2.IMREAD_UNCHANGED)img_png = cv2.imread(img_png_path, cv2.IMREAD_UNCHANGED)# 判斷jpg圖像是否已經(jīng)為4通道if img_jpg.shape[2] == 3:img_jpg = add_alpha_channel(img_jpg)img = handel_img(img_jpg)small_img = handel_img(img_png)res_TM_CCOEFF_NORMED = cv2.matchTemplate(img, small_img, 3)value = cv2.minMaxLoc(res_TM_CCOEFF_NORMED)value = value[3][0] # 獲取到移動(dòng)距離return value# 1. 打開chromedriver,試試下載圖片cs = CrackSlider()cs.get_pic()# 2. 對(duì)比圖片,計(jì)算距離img_jpg_path = 'target.jpg' # 讀者可自行修改文件路徑img_png_path = 'template.png' # 讀者可自行修改文件路徑distance = match(img_jpg_path, img_png_path)distance = distance /480 * 345 + 12# 3. 移動(dòng)cs.crack_slider(distance)
最后感謝每一個(gè)認(rèn)真閱讀我文章的人,禮尚往來總是要有的,雖然不是什么很值錢的東西,如果你用得到的話可以直接拿走:【文末領(lǐng)取】
? ? ?【下面是我整理的2023年最全的軟件測(cè)試工程師學(xué)習(xí)知識(shí)架構(gòu)體系圖+全套資料】
一、Python編程入門到精通

二、接口自動(dòng)化項(xiàng)目實(shí)戰(zhàn)??
三、Web自動(dòng)化項(xiàng)目實(shí)戰(zhàn)

四、App自動(dòng)化項(xiàng)目實(shí)戰(zhàn)?
五、一線大廠簡(jiǎn)歷

六、測(cè)試開發(fā)DevOps體系?
七、常用自動(dòng)化測(cè)試工具

八、JMeter性能測(cè)試?
九、總結(jié)(文末尾部小驚喜)
生命不息,奮斗不止。每一份努力都不會(huì)被辜負(fù),只要堅(jiān)持不懈,終究會(huì)有回報(bào)。珍惜時(shí)間,追求夢(mèng)想。不忘初心,砥礪前行。你的未來,由你掌握!
生命短暫,時(shí)間寶貴,我們無法預(yù)知未來會(huì)發(fā)生什么,但我們可以掌握當(dāng)下。珍惜每一天,努力奮斗,讓自己變得更加強(qiáng)大和優(yōu)秀。堅(jiān)定信念,執(zhí)著追求,成功終將屬于你!
只有不斷地挑戰(zhàn)自己,才能不斷地超越自己。堅(jiān)持追求夢(mèng)想,勇敢前行,你就會(huì)發(fā)現(xiàn)奮斗的過程是如此美好而值得。相信自己,你一定可以做到!???