小豬的Python學習之旅 —— 13.文字識別庫pytesseract初體驗

小豬的Python學習之旅 —— 13.文字識別庫pytesseract初體驗

標籤:Python


引言

度過了短暫的春節假期,又要開始繼續搬磚了,因爲還處於節後
綜合徵,各種散漫,不想看任何代碼相關的東西,根本擠不出學習熱情…
恰逢前幾天,公司的UI妹子安利了一個賣萌的新番:小木乃伊到我家

就是圖中的這四隻小東西,敲可愛的說,分別叫:

小伊(木乃伊),可尼(小鬼,牛),啊勇(龍),胖嘟嘟

UI妹子尤其喜歡可尼,是挺萌的,突然想找些相關的手機或者電腦壁紙,
壁紙沒找到,卻在 小木乃伊到我家吧 裏找到了一些自制的表情包:
https://tieba.baidu.com/p/5522091060

表情都很有趣嘛,寫個腳本把圖片都爬下來?走一波流程:

Step 1:Network抓包看下返回的數據是否和Element一致,
或者說有我們想要的數據,而不是通過JS黑魔法進行加載的;

複製下第一個圖的圖片鏈接,到Network選項卡里的Response
裏查找以下,嗯,找得到,可以:

Step 2:滾動到底,抓包沒有發現Ajax動態加載數據的蹤跡

Step 3:點擊第二頁,抓包發現了Ajax加載的痕跡!!!

同樣拿第一個圖的url搜下,同樣可以找到

三個參數猜測pn爲page_number,即頁數,PostMan或者自己
寫代碼模擬請求,記得塞入Host和X-Requested-With,驗證pn=1
是否爲第一頁數據,驗證通過,即所有頁面數據都可以通過這個
接口拿到;

Step 4:先加載拿到末頁是第幾頁,然後走一波循環遍歷即可
解析數據獲得圖片url,寫入文件,使用多個線程進行下載
比較簡單,就不詳解了,直接給出代碼,看不懂的自己複習去:

# 抓取百度貼吧某個帖子裏的所有圖片
import coderpig_n as cpn
import requests
import time
import threading
import queue

tiezi_url = "https://tieba.baidu.com/p/5522091060"
headers = {
    'Host': 'tieba.baidu.com',
    'User-Agent': cpn.user_agent_dict['chrome'],
}

pic_save_dir = 'output/Picture/BaiduTieBa/'
pic_urls_file = 'tiezi_pic_urls.txt'
download_q = queue.Queue()  # 下載隊列


# 獲得頁數
def get_page_count():
    try:
        resp = requests.get(tiezi_url, headers=headers, timeout=5)
        if resp is not None:
            soup = cpn.get_bs(resp.text)
            a_s = soup.find("ul", attrs={'class': 'l_posts_num'}).findAll("a")
            for a in a_s:
                if a.get_text() == '尾頁':
                    return a['href'].split('=')[1]
    except Exception as e:
        print(str(e))


# 下載線程
class PicSpider(threading.Thread):
    def __init__(self, t_name, func):
        self.func = func
        threading.Thread.__init__(self, name=t_name)

    def run(self):
        self.func()


# 獲得每頁裏的所有圖片
def get_pics(count):
    while True:
        params = {
            'pn': count,
            'ajax': '1',
            't': int(time.time())
        }
        try:
            resp = requests.get(tiezi_url, headers=headers, timeout=5, params=params)
            if resp is not None:
                soup = cpn.get_bs(resp.text)
                imgs = soup.findAll('img', attrs={'class': 'BDE_Image'})
                for img in imgs:
                    cpn.write_str_data(img['src'], pic_urls_file)
                return None
        except Exception as e:
            pass
    pass


# 下載線程調用的方法
def down_pics():
    global download_q
    while not download_q.empty():
        data = download_q.get()
        download_pic(data)
        download_q.task_done()


# 下載調用的方法
def download_pic(img_url):
    while True:
        proxy_ip = {
            'http': 'http://' + cpn.get_dx_proxy_ip(),
            'https': 'https://' + cpn.get_dx_proxy_ip()
        }
        try:
            resp = requests.get(img_url, headers=headers, proxies=proxy_ip, timeout=5)
            if resp is not None:
                print("下載圖片:" + resp.request.url)
                pic_name = img_url.split("/")[-1]
                with open(pic_save_dir + pic_name, "wb+") as f:
                    f.write(resp.content)
                return None
        except Exception as e:
            pass


if __name__ == '__main__':
    cpn.is_dir_existed(pic_save_dir)
    print("檢索判斷鏈接文件是否存在:")
    if not cpn.is_dir_existed(pic_urls_file, mkdir=False):
        print("不存在,開始解析帖子...")
        page_count = get_page_count()
        if page_count is not None:
            headers['X-Requested-With'] = 'XMLHttpRequest'
            for page in range(1, int(page_count) + 1):
                get_pics(page)
        print("鏈接已解析完畢!")
        headers.pop('X-Requested-With')
    else:
        print("存在")
    print("開始下載圖片~~~~")
    headers['Host'] = 'imgsa.baidu.com'
    pic_list = cpn.load_list_from_file(pic_urls_file)
    threads = []
    for pic in pic_list:
        download_q.put(pic)
    for i in range(0, len(pic_list)):
        t = PicSpider(t_name='線程' + str(i), func=down_pics)
        t.daemon = True
        t.start()
        threads.append(t)
    download_q.join()
    for t in threads:
        t.join()
    print("圖片下載完畢")

運行結果

接着在和UI妹子聊天的時候就可以拿這些表情來鬥圖了,但是問題來了,
總共有165個圖,我每次想說什麼都要打開圖片一個個看文字是否
符合場景,然後才發,有點呆,而且浪費時間,有沒有什麼快點
找到表情的方法呢?

答:直接把表情裏的文字作爲圖片名不就好了,直接文件搜索搜關鍵字;

但是問題又來了,一張張去改文件名?多呆哦!

突然想起之前看過一篇頭腦王者答題輔助腳本的文章,就是
利用OCR文字識別,把識別出來的文字丟百度上搜索,選項頻度最高
的一般就是正確答案,可以試一波這個套路,谷歌爲我們提供了一個
免費的ORC文字識別引擎:Tesseract
倉庫地址:https://github.com/tesseract-ocr/tesseract


1.裝一波環境

穩定版本是3.0,4.0版本還處於研發,一開始以爲新版的肯定牛逼
一些,裝了4.0的發現對於中文的識別效率超低,差太遠了,後來
又換回了3.0版本,情況稍微好一些,當然可以通過其他方法提高
中文識別率,圖片裁剪,調節對比度,黃底黑字,自己訓練語言庫等,
不是本節的學習範疇,本節寫個簡單的例子瞭解下怎麼用而已~

更多可移步到:ubuntu下使用Tesseract-ocr(編譯、安裝、使用、訓練新的語言庫)
各個版本介紹:https://github.com/tesseract-ocr/tesseract/wiki/ReleaseNotes


Ubuntu 14.04 環境安裝(其他系統環境後續用到再補充…)

1.安裝tesseract-ocr

sudo apt-get install tesseract-ocr
tesseract --version

2.安裝pytesseractImage

sudo pip install pytesseract
sudo pip install Image

3.下載tesseract中文簡體字庫

默認安裝後是不帶中文簡體庫的,官方倉庫走一波:
https://github.com/tesseract-ocr/tessdata
記得選擇版本Tag,3.0的tesseract-ocr是用不了4.0的字庫的!!!
如果你下錯了,調用的時候會報3.0用不了4.0的字庫的錯誤!!!

這兩個就是對應中文簡體與繁體:

字庫下載後需要放到下面的目錄下:/usr/share/tesseract-ocr/tessdata
然後你發現字庫文件無法拷貝到該目錄下,因爲需要權限,這裏可以通過
命令行拷貝一波:

sudo cp '/home/jay/下載/chi_sim.traineddata' /usr/share/tesseract-ocr/tessdata

前面是源文件,後面是拷貝到哪個目錄下。

好了,到此就準備完成了,接着寫個簡單的程序來識別一波!


2.識別一波圖片

代碼忒簡單,創建一個Image對象,調用下pytesseract.image_to_string()方法
就能識別文字了,參數依次是Image對象,識別語言類型,chi_sim中文簡體

import pytesseract
from PIL import Image

image = Image.open('1.png')
text = pytesseract.image_to_string(image, lang='chi_sim')
print(text.replace(" ", ""))

隨手截一波掘金首頁的分類欄:

運行一波:

識別結果有點感人,調一張表情圖試試:

識別結果:

???都識別出來什麼東西,後面試了幾張圖片我還發現不止識別
錯誤,有時連字都識別不出來…在不自己去訓練字體庫的情況下,
中文識別率真心感人,不過最大的有點優點還是:Tesseract免費
識別數字或者英語的時候,還湊合,隨手複製一段英文:

設置下lang=’eng’,輸出結果:

免費的識別率低,試試收費的怎樣,百度雲OCR


3.試試百度雲OCR

收費每天免費500次,拿來完成我們這個圖片命名的小腳本足矣!
官方文檔文字識別 - Python SDK文檔

配置流程

1.開通文字識別服務https://cloud.baidu.com/product/ocr.html

2.創建一個應用,然後記下API KeySecret Key 程序裏要用

3.點右上角->用戶中心,抄下自己的用戶ID

4.pip命令安裝一波

sudo pip install baidu-aip

編寫簡單代碼

from aip import AipOcr

# 新建一個AipOcr對象
config = {
    'appId': 'XXX',
    'apiKey': 'YYY',
    'secretKey': 'ZZZ'
}
client = AipOcr(**config)


# 讀取圖片
def get_file_content(file_path):
    with open(file_path, 'rb') as fp:
        return fp.read()

# 識別圖片裏的文字
def img_to_str(image_path):
    image = get_file_content(image_path)
    # 調用通用文字識別, 圖片參數爲本地圖片
    result = client.basicGeneral(image)
    # 結果拼接返回
    if 'words_result' in result:
        return '\n'.join([w['words'] for w in result['words_result']])


if __name__ == '__main__':
    print(img_to_str('1.png'))

試試上面掘金的那個,輸出結果:

嘖嘖,可以的,試試搞基那個表情?

嗯,還是有點小錯誤,在文檔裏找到:

basicGeneral 改爲 basicAccurate,結果:

嘖嘖,完美識別,稍微慢了一點點,接下來把代碼完善下,
把所有的圖片重命名一波咯!


4.實戰:利用百度OCR識別自動修改文件名

遍歷文件夾,獲得所有的圖片路徑,然後文字識別一波,獲得結果集
里長度最長的字符串作爲文件名,能識別的就修改下文件名,完整代碼
如下:

import os
from aip import AipOcr

# 新建一個AipOcr對象
config = {
    'appId': 'XXX',
    'apiKey': 'YYY',
    'secretKey': 'ZZZ'
}
client = AipOcr(**config)

pic_dir = r"/home/jay/圖片/BaiduTieBa/"


# 讀取圖片
def get_file_content(file_path):
    with open(file_path, 'rb') as fp:
        return fp.read()


# 識別圖片裏的文字
def img_to_str(image_path):
    image = get_file_content(image_path)
    # 調用通用文字識別, 圖片參數爲本地圖片
    result = client.basicGeneral(image)
    # 結果拼接返回
    words_list = []
    if 'words_result' in result:
        if len(result['words_result']) > 0:
            for w in result['words_result']:
                words_list.append(w['words'])
            file_name = get_longest_str(words_list)
            print(file_name)
            os.rename(image_path, pic_dir + str(file_name).replace("/", "") + '.jpg')


# 獲取字符串列表中最長的字符串
def get_longest_str(str_list):
    return max(str_list, key=len)


# 遍歷某個文件夾下所有圖片
def query_picture(dir_path):
    pic_path_list = []
    for filename in os.listdir(dir_path):
        pic_path_list.append(dir_path + filename)
    return pic_path_list


if __name__ == '__main__':
    pic_list = query_picture(pic_dir)
    if len(pic_list) > 0:
        for i in pic_list:
            img_to_str(i)

運行結果

要注意一點,高精度版免費只有50次,我一開始不知道,後面跑程序
突然卡住一直不動,這點要注意,後面還是用回了普通模式,所以有
些文件名並不完全是對的,就調調API的事,非常簡單,項目有極大
剛需要用到文字識別的自行去官網瞭解吧~


5.小結

本節簡單的瞭解了一下pytesseract這個免費的OCR識別庫,
對於中文的識別率不高,後面試了下百度雲OCR,順道寫了
一個簡單的實戰項目,都比較簡單,那麼本節就到這裏啦~


來啊,Py交易啊

想加羣一起學習Py的可以加下,智障機器人小Pig,驗證信息裏包含:
PythonpythonpyPy加羣交易屁眼 中的一個關鍵詞即可通過;

驗證通過後回覆 加羣 即可獲得加羣鏈接(不要把機器人玩壞了!!!)~~~
歡迎各種像我一樣的Py初學者,Py大神加入,一起愉快地交流學♂習,van♂轉py。


發佈了306 篇原創文章 · 獲贊 1857 · 訪問量 1661萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章