keras的驗證碼識別實戰
keras的驗證碼影象識別
一、簡介
接觸過機器學習的都應該知道,TensorFlow和keras的一個經典的入門例子就是MNIST的手寫圖片識別,具體內容是根據手寫的0-9的圖片,通過機器學習,最後能夠得到手寫圖片的具體數字。
其實,驗證碼的識別和手寫數字的識別區別不過,無非是多了字母,也就是分類變多了,0-9是10類,字母也就是26類,一共36個分類。
以上交所的登入驗證碼為例:
經過研究發現:驗證碼中去除了數字0和1,字母去除了O、I、Q、L,一共6個分類,現在剩餘一共30個分類。
二、資料準備
首先爬取了該網站的10000張驗證碼圖片,然後對圖片進行人工的驗證碼命名:
其次,對驗證碼進行去噪、切分成16*16的4個字母的單個圖片,並且根據圖片的名字,放在不同的資料夾下面,一共可以得到30個資料夾,每個資料夾下面分別放的改分類的單張16 * 16的圖片,如圖所示:
資料夾內部:
這裡只討論驗證碼識別模型的訓練,圖片的去噪和切分不在這裡研究,切分好的圖片需要進行一遍人工的驗證,去掉一些切分錯誤的圖片,保證訓練集和測試集的正確度。在實際切分的時候W和M是切分錯誤比較多的,可能是因為兩個字母相對來說寬一點,程式識別的誤差比較大。
三、keras訓練指令碼的編寫
這裡使用到的keras的庫是TensorFlow中的內建keras庫,和keras的獨立庫總體上相同,有些API的呼叫方面有些許不同。
-
首先匯入對應的庫
TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import kerasHelper libraries
import numpy as np
主要用來畫圖
import matplotlib.pyplot as plt
系統的IO操作
import os
圖片的讀取等相關庫
import matplotlib.image as mpimg
from PIL import Imagesklean
from sklearn import metrics
-
讀取圖片資料
資料的載入把它放入load_data這個方法中,輸入引數為圖片資料所有的父路徑。
首先在在程式初始化時定義所有的分類:
class_names = ['2', '3', '4', '5', '6', '7', '8', '9', 'A','B','C','D','E','F','G','H','J','K','M','N', 'P','R','S','T','U','V','W','X','Y','Z']
通過遍歷分類資料組的資料,來實現遍歷整個圖片資料資料夾的目的,最終實現讀取所有驗證碼圖片並且其標籤的資料。在讀取到具體某張圖片資料時,獲取圖片的畫素矩陣為16 * 16,使用im = Image.open(path)獲取,通過im = (np.expand_dims(im,0))轉換為(1 *16 *16)的矩陣,並且通過numpy的vstack方法使其豎直方向上的疊加至最終的x,x矩陣最終的維度為(圖片數量 * 16 *16)。讀取迴圈中的分類名稱為圖片的標籤,型別轉換是和圖片畫素一樣的道理。
def laod_data(source_dir):
x =None
y =None
for n in range(len(class_names)):
d = source_dir+class_names[n]
ldata = os.listdir(d)
for i in range(0,len(ldata)):
path = os.path.join(d,ldata[i])
im = Image.open(path)
im = Image.fromarray(np.uint8(im))
im = np.array(im) #(16*16)
im = (np.expand_dims(im,0))#(1*16*16)
if x is None:
x = im
else:
x = np.vstack((x,im))
if y is None:
y = n
else:
y = np.vstack((y,n))
return x,y
最後,呼叫其方法獲取訓練資料和測試資料:
print('load data start...')
train_dir = r'C:\\Users\\chenyang\\Desktop\\all\\training\\'
test_dir = r'C:\\Users\\chenyang\\Desktop\\all\\testing\\'
train_images, train_labels = laod_data(train_dir)
print(train_images.shape,train_labels.shape)
test_images, test_labels = laod_data(test_dir)
print(test_images.shape,test_labels.shape)
print('load data end...')
- 定義模型結構
-
在keras中定義模型結構十分的方便,具體程式碼如下:
model = keras.Sequential([
keras.layers.Flatten(input_shape=(16, 16)),
keras.layers.Dense(512, activation=tf.nn.relu),
keras.layers.Dropout(0.4, noise_shape=None, seed=None),
keras.layers.Dense(30, activation=tf.nn.softmax)
])
所有的層級結構都在keras.layer下面,第一層為Flatten,先把輸入的矩陣reshape成一個一維的資料,第二層是一個relu啟用層(ReLu是輸入只能大於0,如果你輸入含有負數,ReLu就不適合,如果你的輸入是圖片格式,ReLu就挺常用的,詳細可以點選這篇文章,裡面說的非常詳細易懂),有512個神經元,這個神經元的數量也是通過多次實驗得到的效果最好的數量。後面是一個Dropout,防止過擬合,在幾次訓練之後發現有過擬合的現象,所以加了一個dropout層,最後是一個softmax,轉換為30個分類的對應概率。
介紹一下model的summary()方法,這個方法會打印出定義模型的整體結構
model.summary()
列印如下:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten (Flatten) (None, 256) 0
_________________________________________________________________
dense (Dense) (None, 512) 131584
_________________________________________________________________
dropout (Dropout) (None, 512) 0
_________________________________________________________________
dense_1 (Dense) (None, 30) 15390
=================================================================
Total params: 146,974
Trainable params: 146,974
Non-trainable params: 0
-
定義優化器和損失函式
model.compile(optimizer=tf.train.AdamOptimizer(),
loss=‘sparse_categorical_crossentropy’,
metrics=[‘accuracy’])
優化器採用AdamOptimizer,這個也是比較常見的優化器,損失函式採用sparse_categorical_crossentropy。
-
開始訓練
epochs = 100 print('training start...') hist = model.fit(train_images, train_labels, epochs=epochs,shuffle=True) test_loss, test_acc = model.evaluate(test_images, test_labels) print('Test accuracy:', test_acc) model.save('./tfmodel.cy') predict = model.predict(test_images)
- model.fit為keras的訓練方法,在這裡輸入的引數有,train_images是我們讀取的圖片畫素的矩陣,train_labels為訓練圖片的標籤,epochs為訓練的迭代輪數,shuffle為訓練的時候是否打亂資料的順序,這個預設是true的,返回一個history物件,這個用處後面會說到。
- model.evaluate是keras的一個評估方法,輸入為測試資料和其標籤,會返回一個損失率和準確率。
- model.save這是keras的模型儲存方法,輸入引數為模型的儲存路徑。對應的有載入方法keras.models.load_model,輸入引數為載入的路徑。
- model.predict是keras的預測方法,輸入為圖片的畫素,返回的結果為預測為每個分類的概率。
輸出:
training start...
Epoch 1/100
27311/27311 [==============================] - 4s 152us/step - loss: 0.6259 - acc: 0.8501
Epoch 2/100
27311/27311 [==============================] - 3s 109us/step - loss: 0.2536 - acc: 0.9357
Epoch 3/100
27311/27311 [==============================] - 3s 127us/step - loss: 0.1968 - acc: 0.9518
Epoch 4/100
27311/27311 [==============================] - 3s 104us/step - loss: 0.1604 - acc: 0.9607
Epoch 5/100
27311/27311 [==============================] - 3s 114us/step - loss: 0.1392 - acc: 0.9664
......中間省略N多
Epoch 96/100
27311/27311 [==============================] - 3s 103us/step - loss: 0.0330 - acc: 0.9929
Epoch 97/100
27311/27311 [==============================] - 3s 97us/step - loss: 0.0348 - acc: 0.9929
Epoch 98/100
27311/27311 [==============================] - 3s 103us/step - loss: 0.0346 - acc: 0.9925
Epoch 99/100
27311/27311 [==============================] - 3s 96us/step - loss: 0.0336 - acc: 0.9930
Epoch 100/100
27311/27311 [==============================] - 3s 105us/step - loss: 0.0306 - acc: 0.9936
11671/11671 [==============================] - 0s 39us/step
Test accuracy: 0.9906606117931984
- F值和混淆矩陣
判斷模型的預測效果的好壞其實關準確率是比較單一的,分類問題中往往用F值、召回率、準確率一起來判斷,這個的計算我們用sklean庫來實現。
pres = []
for i in predict:
tool = np.argmax(i)
pres.append(tool)
tests = []
test_labels = test_labels.T
li = test_labels.tolist()
# 評估
print("Precision, Recall and F1-Score...")
print(metrics.classification_report(li[0],pres,target_names =class_names))
# 混淆矩陣
print("Confusion Matrix...")
cm = metrics.confusion_matrix(li[0],pres)
print(cm)
輸出結果:
Precision, Recall and F1-Score...
precision recall f1-score support
2 0.99 0.98 0.98 359
3 0.99 0.99 0.99 400
4 0.99 1.00 1.00 405
5 0.99 0.98 0.99 384
6 0.99 0.99 0.99 409
7 1.00 0.99 1.00 393
8 1.00 0.99 0.99 417
9 0.99 0.99 0.99 400
A 1.00 0.99 1.00 376
B 0.99 1.00 0.99 368
C 0.99 0.97 0.98 409
D 0.99 1.00 0.99 405
E 1.00 0.99 0.99 411
F 0.99 0.99 0.99 373
G 0.97 0.99 0.98 380
H 0.99 0.99 0.99 353
J 1.00 0.99 0.99 402
K 0.99 1.00 1.00 351
M 0.99 0.99 0.99 362
N 1.00 0.99 1.00 381
P 0.99 0.99 0.99 377
R 0.99 0.99 0.99 407
S 0.99 0.98 0.99 363
T 0.99 0.99 0.99 431
U 1.00 0.99 0.99 384
V 0.98 0.99 0.98 423
W 0.99 0.99 0.99 351
X 1.00 0.99 0.99 413
Y 0.99 0.98 0.99 385
Z 0.98 0.99 0.99 399
avg / total 0.99 0.99 0.99 11671
Confusion Matrix...
[[353 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 6]
[ 0 398 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 405 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 1 0 378 3 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 2 0 0 0 0 0 0 0]
[ 0 0 0 2 406 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 390 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 2]
[ 0 0 0 0 0 0 414 0 0 3 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 1 0 0 0 0 0 395 0 1 0 0 0 0 0 0 0 0
0 0 1 0 1 1 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 374 0 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 1 0 0 367 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0]
[ 2 0 0 0 0 0 0 0 0 0 397 1 1 0 8 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 1 0 0 0 0 0 0 0 0 403 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1]
[ 1 0 0 1 1 0 0 0 0 1 0 0 407 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 2 0 0 0 0 0 0 0 0 0 0 371 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 1 0 0 0 0 0 2 1 0 0 376 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 350 1 0
0 0 0 0 0 0 0 1 0 0 0 0]
[ 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 398 0
0 0 0 0 0 1 0 0 0 0 0 1]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 350
0 0 0 1 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0
360 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 379 0 0 0 0 0 0 1 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 373 4 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 2 404 0 0 0 0 0 0 1 0]
[ 1 1 0 2 0 0 0 0 0 0 0 0 0 0 1 1 0 0
0 0 0 0 357 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 1 0 0 427 1 0 0 0 1 0]
[ 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1
0 0 0 0 0 0 380 1 0 0 0 0]
[ 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 418 1 0 1 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 1 349 0 0 0]
[ 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 2 0 407 1 0]
[ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0
0 0 0 0 0 1 0 3 0 0 379 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 1 0 397]]
- metrics.classification_report(li[0],pres,target_names =class_names)為sklean的分類結果的輸出,輸入引數分別為正常的標籤,預測的標籤,分類的實際名稱
- metrics.confusion_matrix(li[0],pres)為sklean的混淆矩陣的輸入,輸入引數分別為正常的標籤,預測的標籤
- 繪畫訓練過程中的準確率和損失率
這裡就用到了我們model.fit中所返回的history物件,他記錄了訓練中每個迭代的損失率和準確率。然後用matplotlib進行畫圖(matplotlib使用可以檢視部落格https://blog.csdn.net/qq_20989105/article/details/82784010)。
history_dict = hist.history
acc = hist.history['acc']
loss = hist.history['loss']
epochs = range(1, len(acc) + 1)
# "bo" is for "blue dot"
plt.plot(epochs, loss, 'r', label='Training loss')
plt.plot(epochs, acc, 'b', label='Training acc')
# b is for "solid blue line"
plt.title('Training loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
輸出效果:
最後附上完整程式碼
# -*- coding: utf-8 -*-
"""
Created on Tue Sep 18 09:42:55 2018
@author: chenyang
"""
# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras
# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
import os
import matplotlib.image as mpimg
from PIL import Image
from sklearn import metrics
def laod_data(source_dir):
x =None
y =None
for n in range(len(class_names)):
d = source_dir+class_names[n]
ldata = os.listdir(d)
for i in range(0,len(ldata)):
path = os.path.join(d,ldata[i])
#
im = Image.open(path)
im = Image.fromarray(np.uint8(im))
im = np.array(im) #(16*16)
# print(im)
im = (np.expand_dims(im,0))#(1*16*16)
if x is None:
x = im
else:
x = np.vstack((x,im))
if y is None:
y = n
else:
y = np.vstack((y,n))
# print(x.shape)
return x,y
if __name__ == '__main__':
class_names = ['2', '3', '4', '5', '6', '7', '8', '9',
'A','B','C','D','E','F','G','H','J','K','M','N',
'P','R','S','T','U','V','W','X','Y','Z']
epochs = 100
print('load data start...')
train_dir = r'C:\\Users\\chenyang\\Desktop\\all\\training\\'
test_dir = r'C:\\Users\\chenyang\\Desktop\\all\\testing\\'
train_images, train_labels = laod_data(train_dir)
print(train_images.shape,train_labels.shape)
test_images, test_labels = laod_data(test_dir)
print(test_images.shape,test_labels.shape)
print('load data end...')
print('build model start...')
model = keras.Sequential([
keras.layers.Flatten(input_shape=(16, 16)),
keras.layers.Dense(512, activation=tf.nn.relu),
keras.layers.Dropout(0.4, noise_shape=None, seed=None),
keras.layers.Dense(30, activation=tf.nn.softmax)
])
model.summary()
model.compile(optimizer=tf.train.AdamOptimizer(),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
#
print('training start...')
# hist = model.fit(train_images, train_labels, epochs=20,shuffle=True,validation_split=0.2)
hist = model.fit(train_images, train_labels, epochs=epochs,shuffle=True)
test_loss, test_acc = model.evaluate(test_images, test_labels)
print('Test accuracy:', test_acc)
model.save('./tfmodel.cy')
##
model = keras.models.load_model('./tfmodel.cy')
predict = model.predict(test_images)
pres = []
for i in predict:
tool = np.argmax(i)
pres.append(tool)
tests = []
test_labels = test_labels.T
li = test_labels.tolist()
# 評估
print("Precision, Recall and F1-Score...")
print(metrics.classification_report(li[0],pres,target_names =class_names))
# 混淆矩陣
print("Confusion Matrix...")
cm = metrics.confusion_matrix(li[0],pres)
print(cm)
# # 建立一段時間內準確性和損失的圖表
#
history_dict = hist.history
acc = hist.history['acc']
loss = hist.history['loss']
epochs = range(1, len(acc) + 1)
# "bo" is for "blue dot"
plt.plot(epochs, loss, 'r', label='Training loss')
plt.plot(epochs, acc, 'b', label='Training acc')
# b is for "solid blue line"
plt.title('Training loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
相關推薦
keras的驗證碼識別實戰
keras的驗證碼影象識別 一、簡介 接觸過機器學習的都應該知道,TensorFlow和keras的一個經典的入門例子就是MNIST的手寫圖片識別,具體內容是根據手寫的0-9的圖片,通過機器學習,最後能夠得到手寫圖片的具體數字。 其實,驗證碼的識別和手寫數字
linux環境下pytesseract的安裝和央行征信中心的登錄驗證碼識別實戰
int tab 權限 linux a-z 都是 提示 解釋 text 首先是安裝,我參考的是這個 http://blog.csdn.net/xinghun_4/article/details/47860645 我是centos,使用yum yum install pyt
python呼叫pytesseract識別某網站的驗證碼(實戰專案)
一、首先安裝 tesseract-ocr-setup-4.00.00dev.exe 1.直接安裝 2.安裝完之後,將目錄檔案 配置到path中 3.新建一個系統變數,名稱為“ TESSDATA_PREFIX” 內容跟步驟二一樣的內容 二、配置完系統變數之後 1.執
Python爬蟲專案實戰3 | 圖片文字識別(以驗證碼識別為例)
1.專案背景 我在實習過程中,當我抓取環保平臺相關資料時,常常發現有圖片的情況,比如以下這種圖片,所以抓取這種圖片中的資訊是我進行圖片文字識別的動力: 2.專案思路 因為在某一網站中有大量這種想要抓取的圖片,所以我的思路是, 1.先抓取這些圖片的名稱和URL; 2.然後再根
Python 新手實戰之機器學習實現簡單驗證碼識別(一):用PIL簡單繪製驗證碼
驗證碼生成 from PIL import Image, ImageDraw, ImageFont import random, os def draw(): #隨機生成背景顏色 (RGB顏色範圍為0-255,越高越接近白色),背景顏色不宜過深,
深度學習驗證碼識別(-)keras環境搭建
5.如果不適用GPU進行運算,上面步驟就可以進行測試使用keras了,如果需要使用GPU,首先是用Nvidia的顯示卡。 gtx1060,gtx1080都比較不錯,再就是安裝cuda驅動。 進入cuda驅動下載網站:https://developer.nvidia.com/cuda-downloads下載相
python3 網路爬蟲開發實戰 win10環境下 圖形驗證碼識別需要安裝的工具及地址
先下載安裝tesseract exe檔案 tesseract exe檔案安裝下載地址:https://digi.bib.uni-m
Python3.4 12306 2015年3月驗證碼識別
like target bottom edr ocr extra spl apple creat import ssl import json from PIL import Image import requests import re import urllib.r
驗證碼識別
code threshold 識別 div out style end gray .cn # -*- coding: utf-8 -*- import urllib.request, urllib.parse from PIL import Image from pyt
python之驗證碼識別 特征向量提取和余弦相似性比較
wow gif .get extra time ade upd orm log 0.目錄 1.參考2.沒事畫個流程圖3.完整代碼4.改進方向 1.參考 https://en.wikipedia.org/wiki/Cosine_similarity https://zh.wi
驗證碼識別(最簡單之印刷體數字)
轉化 end double show ray app def 藍色 代碼實現 # -*- coding: utf-8 -*- import numpy from PIL import Image image = Image.open("5.gif") heigh
C#驗證碼識別基礎方法實例分析
renren 幫助 流行 人工 esp 導致 edi count public 本文實例講述了C#驗證碼識別基礎方法,是非常實用的技巧。分享給大家供大家參考。具體方法分析如下: 背景 最近有朋友在搞一個東西,已經做的挺不錯了,最後想再完美一點,於是乎就提議把這種驗證碼
深度學習下的驗證碼識別教程
www 2016年 復制 egit 關於 廣泛 效果 yun 概念 轉:https://bbs.125.la/thread-14031313-1-1.html 隨著大數據時代,人工智能時代的到來,深度學習的應用越來越廣,場景識別、目標檢測、人臉識別、圖像識別等等廣泛應用。在
python tesseract-ocr 基礎驗證碼識別功能(Windows)
please 沒有 pan eas pin mage 需要 utf 文件夾 一、環境 windows 7 x64 Python 3 + 二、安裝 1、tesseract-ocr安裝 http://digi.bib.uni-mannheim.
基於SVM的字母驗證碼識別
區域 總結 nim 系列 red clust 記錄 完成 form 基於SVM的字母驗證碼識別 摘要 本文研究的問題是包含數字和字母的字符驗證碼的識別。我們采用的是傳統的字符分割識別方法,首先將圖像中的字符分割出來,然後再對單字符進行識別。首先通過圖像的初步去噪、濾波、形態
python 豆瓣驗證碼識別總結
ops hold 成功 驗證碼識別 濾波 put else 函數 直接 總結: pytesseract 識別比較標準的圖片 識別成功率 還是不錯的。 驗證碼的圖片識別 需要先處理好 再用pytesseract 識別 from PIL import Image
驗證碼識別——圖形驗證碼
img tex 下載 分享 int class 驗證碼 pre imp 先找了一個簡單的圖形驗證碼進行測試,比如知網,從網頁裏把驗證碼下載到本地 進行簡單的灰度處理和二值化處理,能夠提高不少識別正確率 驗證碼: 代碼: 1 import tess
基於TensorFlow的簡單驗證碼識別
mini shu nal array pool 利用 imp 大小寫 標註 TensorFlow 可以用來實現驗證碼識別的過程,這裏識別的驗證碼是圖形驗證碼,首先用標註好的數據來訓練一個模型,然後再用模型來實現這個驗證碼的識別。 生成驗證碼 首先生成驗證碼,這裏使用
驗證碼識別 Tesseract的簡單使用和總結
參數說明 stdout all 令行 github output 一個個 其中 簡單 Tesseract是什麽 OCR即光學字符識別,是指通過電子設備掃描紙上的打印的字符,然後翻譯成計算機文字的過程。也就是說通過輸入圖片,經過識別引擎,去識別圖片上的文字。Tesseract
基於SVM的python簡單實現驗證碼識別
save def lse highlight pro imp bubuko uac 如果 1. 爬取驗證碼圖片 from urllib import request def download_pics(pic_name): url = ‘http://wsbs