目錄
- 前言
- 一、動(dòng)態(tài)驗(yàn)證碼
- 二、滑動(dòng)驗(yàn)證碼
- 三、驗(yàn)證碼的降噪
- 四、驗(yàn)證碼的識(shí)別
- 總結(jié)
前言
python對(duì)動(dòng)態(tài)驗(yàn)證碼、滑動(dòng)驗(yàn)證碼的降噪和識(shí)別,在各種自動(dòng)化操作中,我們經(jīng)常要遇到沿跳過驗(yàn)證碼的操作,而對(duì)于驗(yàn)證碼的降噪和識(shí)別,的確困然了很多的人。這里我們就詳細(xì)講解一下不同驗(yàn)證碼的降噪和識(shí)別。
一、動(dòng)態(tài)驗(yàn)證碼
- 動(dòng)態(tài)驗(yàn)證碼是服務(wù)端生成的,點(diǎn)擊一次,就會(huì)更換一次,這就會(huì)造成很多人在識(shí)別的時(shí)候,會(huì)發(fā)現(xiàn)驗(yàn)證碼一直過期
- 這是因?yàn)椋绻闶前褕D片下載下來,進(jìn)行識(shí)別的話,其實(shí)在下載的這個(gè)請(qǐng)求中,其實(shí)相當(dāng)于點(diǎn)擊了一次,這個(gè)驗(yàn)證碼的內(nèi)容已經(jīng)被更換了
- 最好的方法是,打開這個(gè)頁面后,將頁面進(jìn)行截圖,然后定位到驗(yàn)證碼的位置,將驗(yàn)證碼從截圖上面裁剪下來進(jìn)行識(shí)別,這樣就不會(huì)造成多次請(qǐng)求,驗(yàn)證碼更換的情況了
![](/d/20211017/103b7a7f013ce50d7325f4fb6fca294a.gif)
from selenium import webdriver
from PIL import Image
# 實(shí)例化瀏覽器
driver = webdriver.Chrome()
# 最大化窗口
driver.maximize_window()
# 打開登陸頁面
driver.get(# 你的url地址)
# 保存頁面截圖
driver.get_screenshot_as_file('./screen.png')
# 定位驗(yàn)證碼的位置
location = driver.find_element_by_id('login_yzm_img').location
size = driver.find_element_by_id('login_yzm_img').size
left = location['x']
top = location['y']
right = location['x'] + size['width']
bottom = location['y'] + size['height']
# 裁剪保存
img = Image.open('./screen.png').crop((left,top,right,bottom))
img.save('./code.png')
driver.quit()
二、滑動(dòng)驗(yàn)證碼
- 滑動(dòng)驗(yàn)證碼,通常是兩個(gè)滑塊圖片,將小圖片滑動(dòng)到大圖片上的缺口位置,進(jìn)行重合,即可通過驗(yàn)證
- 對(duì)于滑動(dòng)驗(yàn)證碼,我們就要識(shí)別大圖上面的缺口位置,然后讓小滑塊滑動(dòng)響應(yīng)的位置距離,即可
- 而為了讓你滑動(dòng)起來,更加的擬人化,你需要一個(gè)滑動(dòng)的路徑,模擬人為去滑動(dòng),而不是機(jī)器去滑動(dòng)
![](/d/20211017/b773628befec8d43824745239bbba9cb.gif)
# 下載兩個(gè)滑塊
bg = self.driver.find_element_by_xpath('//*[@id="captcha_container"]/div/div[2]/img[1]').get_attribute('src')
slider = self.driver.find_element_by_xpath('//*[@id="captcha_container"]/div/div[2]/img[2]').get_attribute('src')
request.urlretrieve(bg, os.getcwd() + '/bg.png')
request.urlretrieve(slider, os.getcwd() + '/slider.png')
# 獲取兩個(gè)滑塊偏移量方法
def getGap(self, sliderImage, bgImage):
'''
Get the gap distance
:param sliderImage: the image of slider
:param bgImage: the image of background
:return: int
'''
bgImageInfo = cv2.imread(bgImage, 0)
bgWidth, bgHeight = bgImageInfo.shape[::-1]
bgRgb = cv2.imread(bgImage)
bgGray = cv2.cvtColor(bgRgb, cv2.COLOR_BGR2GRAY)
slider = cv2.imread(sliderImage, 0)
sliderWidth, sliderHeight = slider.shape[::-1]
res = cv2.matchTemplate(bgGray, slider, cv2.TM_CCOEFF)
a, b, c, d = cv2.minMaxLoc(res)
# print(a,b,c,d)
# 正常如下即可
# return c[0] if abs(a) >= abs(b) else d[0]
# 但是頭條顯示驗(yàn)證碼的框跟驗(yàn)證碼本身的像素不一致,所以需要根據(jù)比例計(jì)算
if abs(a) >= abs(b):
return c[0] * bgWidth / (bgWidth - sliderWidth)
else:
return d[0] * bgWidth / (bgWidth - sliderWidth)
# 移動(dòng)路徑方法
def getTrack(self, distance):
'''
Get the track by the distance
:param distance: the distance of gap
:return: list
'''
# 移動(dòng)軌跡
track = []
# 當(dāng)前位移
current = 0
# 減速閾值
mid = distance * 4 / 5
# 計(jì)算間隔
t = 0.2
# 初速度
v = 0
while current distance:
if current mid:
# 加速度為正2
a = 2
else:
# 加速度為負(fù)3
a = -3
# 初速度v0
v0 = v
# 當(dāng)前速度v = v0 + at
v = v0 + a * t
# 移動(dòng)距離x = v0t + 1/2 * a * t^2
move = v0 * t + 1 / 2 * a * t * t
# 當(dāng)前位移
current += move
# 加入軌跡
track.append(round(move))
return track
# 滑動(dòng)到缺口位置
def moveToGap(self, track):
'''
Drag the mouse to gap
:param track: the track of mouse
:return: None
'''
ActionChains(self.driver).click_and_hold(self.driver.find_element_by_xpath('//*[@id="captcha_container"]/div/div[3]/div[2]/div[2]/div')).perform()
while track:
x = random.choice(track)
ActionChains(self.driver).move_by_offset(xoffset=x, yoffset=0).perform()
track.remove(x)
time.sleep(0.5)
ActionChains(self.driver).release().perform()
三、驗(yàn)證碼的降噪
驗(yàn)證碼的降噪,只是為了處理驗(yàn)證碼圖像上的多余的線條和干擾線,讓你后期識(shí)別更加的準(zhǔn)確,提高識(shí)別的準(zhǔn)確度
第一步:可以進(jìn)行灰度轉(zhuǎn)化
![](/d/20211017/dc1b715d42ffe16cf4aa04d03b5260e9.gif)
![](/d/20211017/3e7326bc0ab4f53a1f93e7b500426657.gif)
img = cv2.imread('yzm.png')
# 將圖片灰度化處理,降維,加權(quán)進(jìn)行灰度化c
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('min_gray',gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
第二步: 二值化處理
![](/d/20211017/2fb0bf46e7112e0c1d7624666e59bda8.gif)
import cv2
img = cv2.imread('yzm.png')
# 將圖片灰度化處理,降維,加權(quán)進(jìn)行灰度化c
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
t,gray2 = cv2.threshold(gray,220,255,cv2.THRESH_BINARY)
cv2.imshow('threshold',gray2)
cv2.waitKey(0)
cv2.destroyAllWindows()
第三步:噪點(diǎn)過濾
![](/d/20211017/a3809c13b83400230616f8e4affde6ea.gif)
import cv2
img = cv2.imread('yzm.png')
# 將圖片灰度化處理,降維,加權(quán)進(jìn)行灰度化c
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
t,gray2 = cv2.threshold(gray,220,255,cv2.THRESH_BINARY)
def remove_noise(img, k=4):
img2 = img.copy()
# img處理數(shù)據(jù),k過濾條件
w, h = img2.shape
def get_neighbors(img3, r, c):
count = 0
for i in [r - 1, r, r + 1]:
for j in [c - 1, c, c + 1]:
if img3[i, j] > 10: # 純白色
count += 1
return count
# 兩層for循環(huán)判斷所有的點(diǎn)
for x in range(w):
for y in range(h):
if x == 0 or y == 0 or x == w - 1 or y == h - 1:
img2[x, y] = 255
else:
n = get_neighbors(img2, x, y) # 獲取鄰居數(shù)量,純白色的鄰居
if n > k:
img2[x, y] = 255
return img2
result = remove_noise(gray2)
cv2.imshow('8neighbors', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
四、驗(yàn)證碼的識(shí)別
通常我們會(huì)使用tesserocr識(shí)別驗(yàn)證碼,但是這個(gè)庫有很大的局限性,識(shí)別率低,即時(shí)降噪效果很好,有很少的線條,也會(huì)不準(zhǔn)確,這種識(shí)別方式并不十分推薦
所以我們一般會(huì)使用第三方的接口進(jìn)行識(shí)別,比如阿里的圖片識(shí)別、騰訊也都是有的
這些第三方接口需要自己接入識(shí)別接口
#識(shí)別降噪后的圖片
code = tesserocr.image_to_text(nrImg)
#消除空白字符
code.strip()
#打印
print(code)
總結(jié)
到此這篇關(guān)于python自動(dòng)化操作之動(dòng)態(tài)驗(yàn)證碼、滑動(dòng)驗(yàn)證碼的降噪和識(shí)別的文章就介紹到這了,更多相關(guān)python動(dòng)態(tài)驗(yàn)證碼降噪和識(shí)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- python驗(yàn)證碼識(shí)別教程之灰度處理、二值化、降噪與tesserocr識(shí)別
- python驗(yàn)證碼識(shí)別的實(shí)例詳解
- Python驗(yàn)證碼識(shí)別處理實(shí)例
- python驗(yàn)證碼識(shí)別教程之利用滴水算法分割圖片
- python簡(jiǎn)單驗(yàn)證碼識(shí)別的實(shí)現(xiàn)方法
- 詳解Python驗(yàn)證碼識(shí)別
- python驗(yàn)證碼識(shí)別教程之利用投影法、連通域法分割圖片
- python爬蟲之自動(dòng)登錄與驗(yàn)證碼識(shí)別
- 使用python 對(duì)驗(yàn)證碼圖片進(jìn)行降噪處理
- python對(duì)驗(yàn)證碼降噪的實(shí)現(xiàn)示例代碼