驗證碼有圖形驗證碼、極驗滑動驗證碼、點觸驗證碼、宮格驗證碼。這回重點講講圖形驗證碼的識別。css
雖然說圖形驗證碼最簡單,可是對於我這等新手,仍是要苦學一番。首先尋找測試網站,網站選的是如雲閣小說網,小網站不怕被封。他們的驗證碼通常以下:web
能夠看出有微弱的干擾線和較強的干擾點,驗證碼是沒有邊框的,這裏爲了排版好看,我加上去的...瀏覽器
1. 灰度處理 把彩色驗證碼圖片轉爲灰色的圖片。cookie
import cv2
image = cv2.imread('1.jpeg', 0)
cv2.imwrite('1.jpg', image)
機器學習
2. 二值化處理 將圖片處理爲只有黑白兩色的圖片,這裏發現干擾線沒有了,這就意味着咱們只須要處理干擾點便可。ide
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個區域。
網站
①②③點座標以下圖,同理可知④⑤⑥⑦⑧⑨點座標狀況
ui
降噪代碼以下:
import cv2
import numpy as np
from PIL import Image
def inverse_color(image, col_range):
# 讀取圖片,0意味着圖片變爲灰度圖
image = cv2.imread(image, 0)
# 圖片二值化,100爲設置閥值,255爲最大閥值,1爲閥值類型,當前點值大於閥值,設置爲0,不然設置爲255。ret是return value縮寫,表明當前的閥值
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: # 左上頂點,4鄰域
# 中心點旁邊3個點
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: # 最上非頂點,6鄰域
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: # 左下頂點
# 中心點旁邊3個點
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: # 最下非頂點,6鄰域
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: # y不在邊界
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: # 具有9領域條件的
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 ···