爬蟲程式會遇到各色各樣的驗證碼,整理一下解決方法,
1.使用均值哈希演算法進行影像識別
原理是根據像素平均值對比,來得到一串01010001這樣的字串,通過比較相同位置上是否相同,
統計出來的數量作為相似度憑據,
適用于不規則,難以識別文字或字母時的影像對比,適用面不廣,但思路可以借鑒,
代碼如下:
#開發時間: 2022/11/2 20:42
import cv2
from PIL import Image
import numpy as np
#改這里!!!
path = r"E:\pic\123\8.jpg"#要識別的主影像
path8 = r"E:\pic\123"#這里存放那0-7編號的八張圖片所在檔案夾地址,不需要加\,如E:\pic
#均值哈希演算法
def aHash(img):
image = cv2.imread(img)
# 縮放為10*10
img = cv2.resize(image, (10, 10))
# 轉換為灰度圖
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# s為像素和初值為0,hash_str為hash值初值為''
s = 0
hash_str = ''
# 遍歷累加求像素和
for i in range(10):
for j in range(10):
s = s + gray[i, j]
# 求平均灰度
avg = s / 100
# 灰度大于平均值為1相反為0生成圖片的hash值
for i in range(10):
for j in range(10):
if gray[i, j] > avg:
hash_str = hash_str + '1'
else:
hash_str = hash_str + '0'
return hash_str
def cmpHash(hash1, hash2):
n = 0
# hash長度不同則回傳-1代表傳參出錯
if len(hash1)!=len(hash2):
return -1
# 遍歷判斷
for i in range(len(hash1)):
# 不相等則n計數+1,n最終為相似度
if hash1[i] != hash2[i]:
n = n + 1
return n
def chanese2num(image1):
hash1 = aHash(image1)
n1 = 0
for i in range(8):
image2 = path8+ "/" +str(i) + ".jpg"
blackwhite(image2, 0)
hash2 = aHash(image2)
n = 100 - cmpHash(hash1, hash2)
# print(n,i)#除錯用
if n >= n1:
n1 = n
num = i
return num
def blackwhite(input_img_file,flag):
"""
轉化為二值影像
"""
img = Image.open(input_img_file)
# 模式L”為灰色影像,它的每個像素用8個bit表示,0表示黑,255表示白,其他數字表示不同的灰度,
Img = img.convert('L')
table = []
if flag == 0:
#處理藍底白字
threshold = 180
for i in range(256):
if i < threshold:
table.append(1)
else:
table.append(0)
photo = Img.point(table, '1')
photo.save(input_img_file)
if flag == 1:
#處理白底紅字
threshold = 228
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
photo = Img.point(table, '1')
photo.save(r"E:\pic\123/test.jpg")
def main():
image = cv2.imread(path)
image = np.array(image)
frame1 = image[2:32, 140:211]#裁剪影像,必須在opencv的陣列影像格式下才成立
save_file = r"E:\pic\123\test.jpg"
# cv2.imshow('666', image)
cv2.imencode('.jpg', frame1)[1].tofile(save_file) # 防止出現亂碼
blackwhite(save_file, 1) # 處理需要識別的并覆寫原影像
num = chanese2num(save_file)
return num
# cv2.waitKey(0)
if __name__ == '__main__':
num = main()
print(f"編號是{num}的圖片是相似度最高的")
"""
在爬蟲程式里這樣呼叫:
my_crawler是你存放這個代碼的檔案夾
from my_crawler import yanzhengma2
if __name__ == '__main__':
num = yanzhengma2.main()
print(num)
#num就是你需要的編號
"""
2.使用pytesseract進行識別
我用來識別過文字,但效果很差勁,對于文字間隔,像素質量要求很嚴格,
整體來說效果不好
import pytesseract
import numpy as np
from PIL import Image
def threshold_By_OTSU(input_img_file):
newimage = Image.open(input_img_file).convert('L') # 打開圖片時候用convert('L')方法轉換為灰點
newimage.save(r"E:\pic\123/9.jpg")
print(pytesseract.image_to_string(newimage, lang='chi_sim'))
file=r'E:\pic\123\8.jpg'
threshold_By_OTSU(file)
這里使用時,遇到了opencv中讀取圖片,和PIL中Image讀取圖片的不同方式,之后再仔細研究一下使用規范
3.使用ddddocr進行識別
帶帶弟弟是一個非常強大的驗證碼識別工具,可以識別漢字,滑塊,點擊文字等許多種類的驗證碼
github原始碼:https://github.com/sml2h3/ddddocr
pypi官方:https://pypi.org/project/ddddocr/
對于文字識別,代碼如下:
import os
import ddddocr
from PIL import Image
from io import BytesIO
ALLOW_FILE_TYPE = ['jpg', 'png']
ocr = ddddocr.DdddOcr(show_ad = False)
def ocr_detect(path):
"""
OCR漢字識別
"""
fp, code = None, None
if not os.path.exists(path): return code
_, file_type = path.rsplit(".",1)
if file_type.lower() not in ALLOW_FILE_TYPE: return code
try:
fp = open(path, 'rb')
con1 = fp.read()
img = Image.open(BytesIO(con1))
code = ocr.classification(img)
except Exception as exc:
print('[ERROR] 識別發生錯誤:', exc)
finally:
if fp: fp.close()
return code
if __name__ == '__main__':
code = ocr_detect(r'E:\pic\123\test.jpg')
for i in range(8):
code2 = ocr_detect(f'E:\pic/123/{i}.jpg')
if code == code2:
print(f"編碼為{i}的是對的")
else:
print("寄了")
具體使用方式參考官方檔案即可
更多方法用到后會繼續更新~
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/527782.html
標籤:Python
上一篇:編譯型語言與解釋型語言
下一篇:[Python]解密pyc檔案
