驗證碼有圖形驗證碼、極驗滑動驗證碼、點觸驗證碼、宮格驗證碼。這回重點講講圖形驗證碼的識別。
雖說圖形驗證碼最簡單,但是對於我這等新手,還是要苦學一番。首先尋找測試網站,網站選的是如雲閣小說網,小網站不怕被封。他們的驗證碼一般如下:
可以看出有微弱的幹擾線和較強的幹擾點,驗證碼是沒有邊框的,這裡為了排版好看,我加上去的...
1. 灰度處理 把彩色驗證碼圖片轉為灰色的圖片。
import cv2
image = cv2.imread('1.jpeg', 0)
cv2.imwrite('1.jpg', image)
2. 二值化處理 將圖片處理為只有黑白兩色的圖片,這裡發現幹擾線沒有了,這就意味著我們只需要處理幹擾點即可。
import cv2
image = cv2.imread('1.jpeg', 0)
ret, image = cv2.threshold(image, 100, 255, 1)
height, width = image.shape
new_image = image[0:height, 0:150]
cv2.imwrite('1.jpg', new_image)
3. 降噪處理 去除小黑點,也就是孤立的黑色像素點。
點降噪原理就是檢測黑色點相鄰的8個點,判斷8個點的顏色情況。如果全是白點,那麼就認為這個點是白色的,做黑點變白點處理。如⑤點處,以田字格來看,相鄰共有8個區域。
①②③點坐標如下圖,同理可知④⑤⑥⑦⑧⑨點坐標情況
降噪代碼如下:
import cv2
import numpy as np
from PIL import Image
def inverse_color(image, col_range):
image = cv2.imread(image, 0)
ret, image = cv2.threshold(image, 110, 255, 1)
height, width = image.shape
img2 = image.copy()
for i in range(height):
for j in range(width):
img2[i, j] = (255 - image[i, j])
img = np.array(img2)
height, width = img.shape
new_image = img[0:height, col_range[0]:col_range[1]]
cv2.imwrite('handle_one.png', new_image)
image = Image.open('handle_one.png')
return image
def clear_noise(img):
x, y = img.width, img.height
for i in range(x):
for j in range(y):
if sum_9_region(img, i, j) < 2:
img.putpixel((i, j), 255)
img = np.array(img)
cv2.imwrite('handle_two.png', img)
img = Image.open('handle_two.png')
return img
def sum_9_region(img, x, y):
"""
田字格
"""
cur_pixel = img.getpixel((x, y))
width = img.width
height = img.height
if cur_pixel == 255:
return 10
if y == 0:
if x == 0:
sum_1 = cur_pixel + img.getpixel((x, y + 1)) + img.getpixel((x + 1, y)) + img.getpixel((x + 1, y + 1))
return 4 - sum_1 / 255
elif x == width - 1:
sum_2 = cur_pixel + img.getpixel((x, y + 1)) + img.getpixel((x - 1, y)) + img.getpixel((x - 1, y + 1))
return 4 - sum_2 / 255
else:
sum_3 = img.getpixel((x - 1, y)) + img.getpixel((x - 1, y + 1)) + cur_pixel + img.getpixel((x, y + 1)) + img.getpixel((x + 1, y)) + img.getpixel((x + 1, y + 1))
return 6 - sum_3 / 255
elif y == height - 1:
if x == 0:
sum_4 = cur_pixel + img.getpixel((x + 1, y)) + img.getpixel((x + 1, y - 1)) + img.getpixel((x, y - 1))
return 4 - sum_4 / 255
elif x == width - 1:
sum_5 = cur_pixel + img.getpixel((x, y - 1)) + img.getpixel((x - 1, y)) + img.getpixel((x - 1, y - 1))
return 4 - sum_5 / 255
else:
sum_6 = cur_pixel + img.getpixel((x - 1, y)) + img.getpixel((x + 1, y)) + img.getpixel((x, y - 1)) + img.getpixel((x - 1, y - 1)) + img.getpixel((x + 1, y - 1))
return 6 - sum_6 / 255
else:
if x == 0:
sum_7 = img.getpixel((x, y - 1)) + cur_pixel + img.getpixel((x, y + 1)) + img.getpixel((x + 1, y - 1)) + img.getpixel((x + 1, y)) + img.getpixel((x + 1, y + 1))
return 6 - sum_7 / 255
elif x == width - 1:
sum_8 = img.getpixel((x, y - 1)) + cur_pixel + img.getpixel((x, y + 1)) + img.getpixel((x - 1, y - 1)) + img.getpixel((x - 1, y)) + img.getpixel((x - 1, y + 1))
return 6 - sum_8 / 255
else:
sum_9 = img.getpixel((x - 1, y - 1)) + img.getpixel((x - 1, y)) + img.getpixel((x - 1, y + 1)) + img.getpixel((x, y - 1)) + cur_pixel + img.getpixel((x, y + 1)) + img.getpixel((x + 1, y - 1)) + img.getpixel((x + 1, y)) + img.getpixel((x + 1, y + 1))
return 9 - sum_9 / 255
def main():
img = '1.jpeg'
img = inverse_color(img, (0, 160))
clear_noise(img)
if __name__ == '__main__':
main()
解決最大的問題後,接下來就是實現自動登陸。首先使用selenium自動點擊登陸按鈕。
到登陸界面後,利用selenium自動輸入用戶名,密碼,對驗證碼區域進行截圖。而後對驗證碼截圖進行處理,最後成功獲取驗證碼。
這裡為什麼是截圖呢,原因是驗證碼圖片一直在變化。比如說我現在複製這個8863驗證碼的圖片連結,在新的標籤頁打開,會發現驗證碼改變了,不是8863,而是另外一張驗證碼圖片。那麼我們通過獲取當前頁面的驗證碼連結,從而來獲取驗證碼圖片,這種方法肯定是不可行的。
通過查閱相關資料,知道了帶cookies訪問驗證碼連結頁面,能夠成功解決這個問題。不過由於相關的庫沒導入成功,也就放棄了。等下回做驗證碼機器學習的時候,再給予解決。
登陸成功
自動登陸代碼如下:
import re
import cv2
import time
import numpy as np
import pytesseract
from PIL import Image
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
USER = '你的用戶名'
PASSWORD = '你的密碼'
browser = webdriver.Chrome()
wait = WebDriverWait(browser, 20)
def inverse_color(image, col_range):...
def clear_noise(img):...
def sum_9_region(img, x, y):...
def auto_login():
"""
實現網頁自動登陸
"""
url = 'http://www.quanben9.com/'
browser.get(url)
button = browser.find_element_by_css_selector('#top1 > div > a:nth-child(3)')
button.click()
input_first = browser.find_element_by_name('username')
input_first.send_keys(USER)
input_second = browser.find_element_by_name('password')
input_second.send_keys(PASSWORD)
browser.save_screenshot('Login_page.png')
photo = Image.open('login_page.png')
box = (1210, 710, 1360, 755)
photo.crop(box).save('Verification.png')
handle_verification_code('Verification.png')
image = Image.open('handle_two.png')
image.show()
result = pytesseract.image_to_string(image)
result = re.sub('[a-zA-Z』!"#$%&'()*+,-./:;<=>?@,。?★、…【】《》?「」『』![\]^_`{|}~]+', '', result.replace(' ', ''), re.S)
print(result)
if len(result) == 4:
input_third = browser.find_element_by_name('code')
input_third.send_keys(result)
time.sleep(2)
button_2 = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'body > div.main > div > form > ul > li:nth-child(5) > input[type="submit"]')))
button_2.click()
time.sleep(5)
else:
return auto_login()
def handle_verification_code(img):
img = inverse_color(img, (0, 160))
img = clear_noise(img)
return img
def main():
auto_login()
if __name__ == '__main__':
main()
exit()
這裡用會聲會影給視頻加了個BGM,不過結尾的時候不是很搭,水平有限吶!還是得好好多學習。視頻如下:
··· END ···
●編號582,輸入編號直達本文
●輸入m獲取文章目錄
算法與數據結構
更多推薦《25個技術類公眾微信》
涵蓋:程序人生、算法與數據結構、黑客技術與網絡安全、大數據技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。