前言
python對動(dòng)態(tài)驗(yàn)證碼、滑動(dòng)驗(yàn)證碼的降噪和識(shí)別,在各種自動(dòng)化操作中,我們經(jīng)常要遇到沿跳過驗(yàn)證碼的操作,而對于驗(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è)請求中,其實(shí)相當(dāng)于點(diǎn)擊了一次,這個(gè)驗(yàn)證碼的內(nèi)容已經(jīng)被更換了
- 最好的方法是,打開這個(gè)頁面后,將頁面進(jìn)行截圖,然后定位到驗(yàn)證碼的位置,將驗(yàn)證碼從截圖上面裁剪下來進(jìn)行識(shí)別,這樣就不會(huì)造成多次請求,驗(yàn)證碼更換的情況了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
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)證
- 對于滑動(dòng)驗(yàn)證碼,我們就要識(shí)別大圖上面的缺口位置,然后讓小滑塊滑動(dòng)響應(yīng)的位置距離,即可
- 而為了讓你滑動(dòng)起來,更加的擬人化,你需要一個(gè)滑動(dòng)的路徑,模擬人為去滑動(dòng),而不是機(jī)器去滑動(dòng)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
# 下載兩個(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)化
1
2
3
4
5
6
7
|
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() |
第二步: 二值化處理
1
2
3
4
5
6
7
8
9
10
11
12
|
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)過濾
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
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í)別接口
1
2
3
4
5
6
7
8
|
#識(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)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://blog.csdn.net/weixin_41635750/article/details/119950411