使用python解析pdf文檔中的單詞導入到有道雲詞典中

筆者最近在備考關於100天后專升本考試,對於現在疫情影響,輔導班也開了對應的網課,筆者從輔導班回家的時候一本書都沒有拿,後來老師在羣裏發了紙質書的pdf版本,讓我們背單詞,在學習單詞的時候不會讀音要一個一個去有道雲等等相關軟件翻譯找到讀音是一件比較麻煩和浪費時間的事情,便有了此文 我整個寫完代碼時間大概用了4個小時左右 共計150多行的python代碼

思路爲:PDF->PNG->txt->xml
將老師發來的pdf版本轉換爲圖片,再用識圖解析成txt文本,再用正則表達式提取單詞到txt中,最後再解析成可被有道雲識別的xml生詞本格式。

1.pdf Convert to png
依賴庫:pip install pymupdf

import sys, fitz
import os
import datetime
def pdf_convert_png(pdfPath, imagePath):
    startTime_pdf2img = datetime.datetime.now()#開始時間
    print("imagePath="+imagePath)
    pdfDoc = fitz.open(pdfPath)
    for pg in range(pdfDoc.pageCount):
        page = pdfDoc[pg]
        rotate = int(0)
        # 每個尺寸的縮放係數爲1.3,這將爲我們生成分辨率提高2.6的圖像。
        # 此處若是不做設置,默認圖片大小爲:792X612, dpi=96
        zoom_x = 1.33333333 #(1.33333333-->1056x816)   (2-->1584x1224)
        zoom_y = 1.33333333
        mat = fitz.Matrix(zoom_x, zoom_y).preRotate(rotate)
        pix = page.getPixmap(matrix=mat, alpha=False)
        
        if not os.path.exists(imagePath):#判斷存放圖片的文件夾是否存在
            os.makedirs(imagePath) # 若圖片文件夾不存在就創建
        
        pix.writePNG(imagePath+'/'+'images_%s.png' % pg)#將圖片寫入指定的文件夾內
        
    endTime_pdf2img = datetime.datetime.now()#結束時間
    print('pdf2img時間=',(endTime_pdf2img - startTime_pdf2img).seconds)
 

讀取所在目錄下所有類型是pdf的文件返回一個包含所有pdf路徑的list

def reload_pdf_path(pdfPath):
    pdf_files = []; #存儲將要轉換pdf的名稱
    for filename in os.listdir(pdfPath):
        if filename.endswith('pdf'):
            pdf_files.append(filename);
    return pdf_files;

 轉換結果:

我擦9-16pdf在末尾了,這可不行 倒時候要按組排序整進去呢 用了List.sort方法也不行 艹

 用正則排序:

pdf_files = sorted(pdf_files,key = lambda i:int(re.match(r'(\d+)',i).group()))

print(pdf_files);

效果:

呵呵 我真是個帶天才

 轉換了一共12篇pdf

可還行一個沒有漏

簡單封裝下代碼留着一會用

2.圖文識別【OCR識別】
簡單看了下其他博主寫的圖文識別,覺得效果都不太好,像我這種圖片那麼複雜的估計會很難識別,這裏去找了下大廠提供的API嘗試

華爲的:

有點貴呀...

百度大法好

試下百度的demo

這個效果..還是免費的..我愛了..

 小試牛刀,識別效果還是很棒的

這裏就還有一個難題就是

這裏我沒有使用正則,而是換了一種方式查找字符串中的[然後往前用切片就能得到單詞,這種正確率不是很高 但是我懶得[我不會正則]整了

for i in png_json['words_result']:
        flag_index = i['words'].find('[');
        #過濾出單詞
        #字符串查找[符號獲得下標後使用字符串切片
        #過濾掉除了英文的東西
        if flag_index !=-1 and i['words'][:flag_index].isalpha():
            print(i['words'][:flag_index]);
            word_list.append(i['words'][:flag_index]);

這裏就得到了單詞,然後下一步就是將單詞寫入xml中

'''
將解析出的單詞寫成有道雲詞典的xml

'''
def word_convert_xml(word_list,xml_name):
    xml_file = open(xml_name,'w');
    xml_file.write('<wordbook>') #xml起始位置
    for word in word_list:
        xml_file.write('<item>')
        xml_file.write('    <word>' + word + '</word>\n')
        xml_file.write('    <trans>' + '<![CDATA[]]>' +  '</trans>\n')
        xml_file.write('    <tags>'+"游龍當歸海"+'</tags>\n') #reading是你單詞本的名字,你可以改成自己的
        xml_file.write('    <progress>1</progress>\n')
        xml_file.write('</item>')
    xml_file.write('</wordbook>')#xml結束位置
# word_convert_xml(test_list,'d1.xml');
# print("單詞個數:",len(test_list));

 這裏就大功告成了,下面是詳細代碼,簡單分爲3個模塊

1.pdf 轉圖片
2.圖片解析出單詞
3.單詞寫入xml
 

'''
pdf_convert_png.py
解析pdf爲png圖片
'''

import sys, fitz
import os
import datetime
import re;
from setting import pdf_path,image_path;

png_count = 0;


def pdf_convert_png(pdf_path,pdf_file_name, imagePath,count):
    global png_count;
    complete_pdf_path = pdf_path+"/"+pdf_file_name;
    #print("完整路徑:"+complete_pdf_path);
    pdfDoc = fitz.open(complete_pdf_path)
    for pg in range(pdfDoc.pageCount):
        page = pdfDoc[pg]
        rotate = int(0)
        # 每個尺寸的縮放係數爲1.3,這將爲我們生成分辨率提高2.6的圖像。
        # 此處若是不做設置,默認圖片大小爲:792X612, dpi=96
        zoom_x = 2 #(1.33333333-->1056x816)   (2-->1584x1224)
        zoom_y = 2
        mat = fitz.Matrix(zoom_x, zoom_y).preRotate(rotate)
        pix = page.getPixmap(matrix=mat, alpha=False)
        
        if not os.path.exists(imagePath):#判斷存放圖片的文件夾是否存在
            os.makedirs(imagePath) # 若圖片文件夾不存在就創建
        
        pix.writePNG(imagePath+'/'+str(count)+'-images_%s.png' % pg)#將圖片寫入指定的文件夾內
        png_count = png_count + 1;
    print("[.]解析成png圖片數:",png_count);

def reload_fileNames(pdfPath,types):
    pdf_files = []; #存儲將要轉換pdf的名稱
    for filename in os.listdir(pdfPath):
        if filename.endswith(types):
            pdf_files.append(filename);
    print("裝載文件個數:{} 文件類型:{}".format(len(pdf_files),types));
    return pdf_files;
# if __name__ == "__main__":
#     pdf_files = reload_fileNames(pdfPath,'pdf');
#     #對文件名稱排序
#     pdf_files = sorted(pdf_files,key = lambda i:int(re.match(r'(\d+)',i).group()))
#     print(pdf_files);
#     count = 1;
#     for p in pdf_files:
#         print("當前轉換pdf:{}".format(p));
#         pdf_convert_png(pdf_path,p, image_path,count)
#         count = count + 1; #計算pdf數量

 


'''
png_convert_word.py
解析png圖片中的單詞
'''
import requests
import base64
from pdf_convert_png import reload_fileNames;
from setting import SK,AK;
from setting import pdf_path,image_path;
word_list=[]; 



#1.調用鑑權接口獲取token
# client_id 爲官網獲取的AK, client_secret 爲官網獲取的SK
def get_token(ak,sk):    #有效日期爲30天
    token ="";
    host = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id="+AK+"&client_secret="+SK;
    print("host:"+host);
    response = requests.get(host)
    if response:
        #print(response.json())
        token = response.json();
        token = token['access_token'];
    elif(response.status_code==400):
        print("獲取token失敗,請檢查AK和SK是否過期");
    return token;
# 二進制方式打開圖片文件
def png_convert_json(token,filename):
    request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic"
    f = open(filename, 'rb')
    img = base64.b64encode(f.read())
    params = {"image":img}
    access_token = token;
    request_url = request_url + "?access_token=" + access_token
    headers = {'content-type': 'application/x-www-form-urlencoded'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        return response.json(); #返回識別json結果
        #print (response.json())
def png_convert_word(file_name,file_path): #傳入文件路徑和文件名
    global word_list;
    #print("..................解析圖片爲單詞開始..................");
    #token = get_token(AK,SK); 
    #2020年2月23日00:52:00 token = 24.e1aea6**e***e532c.2**2000.158498**44.28233**-18**149
    token = "24.e****69d2f691b534e885e62***ce532c.2592000.1584982244.282335-18553149";
    #file_name = "../png/1-images_0.png";
    complete_path = file_path+"/"+file_name;
    print("當前操作文件:{}".format(complete_path));

    png_json = png_convert_json(token,complete_path);
    #json文件 words_result_num 檢測數量 words_result['words'] 檢測結果
    #print("識別數量:",png_json['words_result_num']);
    for i in png_json['words_result']:
        flag_index = i['words'].find('[');
        #過濾出單詞
        #字符串查找[符號獲得下表後使用字符串切片
        #過濾掉除了英文的東西
        if flag_index !=-1 and i['words'][:flag_index].isalpha():
            print(i['words'][:flag_index]);
            word_list.append(i['words'][:flag_index]);
    print("識別單詞個數:{}".format(len(word_list)));
    #return word_list;

# if __name__ == "__main__":
#     png_files = reload_fileNames(image_path,'png')
#     #print(png_files);
#     for png_file_name in png_files:
#         png_convert_word(png_file_name,image_path);
#         #input();
#     print("識別單詞個數:",len(word_list));
#     print(word_list);

 

'''
word_convert_XML.py

將解析出的單詞寫成有道雲詞典的xml

'''
def word_convert_xml(word_list,xml_name):
    xml_file = open(xml_name,'w');
    xml_file.write('<wordbook>') #xml起始位置
    for word in word_list:
        xml_file.write('<item>')
        xml_file.write('    <word>' + word + '</word>\n')
        xml_file.write('    <trans>' + '<![CDATA[]]>' +  '</trans>\n')
        xml_file.write('    <tags>'+"游龍當歸海"+'</tags>\n') #reading是你單詞本的名字,你可以改成自己的
        xml_file.write('    <progress>1</progress>\n')
        xml_file.write('</item>')
    xml_file.write('</wordbook>')#xml結束位置
# word_convert_xml(test_list,'d1.xml');
# print("單詞個數:",len(test_list));

還有一個公共變量setting.py

pdf_path = '../Word'  #pdf所在的路徑
image_path = '../png' #存放圖片所在的位置
AK="wymGK1blbN**RL4eemjkF"; #api key
SK= "PLfqdTh7j**FqcVk6kIteqY" #secert key

 最後是主文件main.py
 

from  pdf_convert_png import *;
from png_convert_word import*;
from word_convert_XML import *;
#from png_convert_word import word_list;
from setting import*;



def main():
    print("................PDF To PNG................");
    pdf_files = reload_fileNames(pdf_path,'pdf');
    #對文件名稱排序
    pdf_files = sorted(pdf_files,key = lambda i:int(re.match(r'(\d+)',i).group()))
    #print(pdf_files);
    count = 0;
    for p in pdf_files:
        #print("當前轉換pdf:{}".format(p));
        pdf_convert_png(pdf_path,p, image_path,count)
        count = count + 1; #計算pdf數量
    print("[.]抓取pdf文件個數:{}".format(count));
    print("................PNG to Word................")
    png_files = reload_fileNames(image_path,'png')
    # #print(png_files);
    for png_file_name in png_files:
        png_convert_word(png_file_name,image_path);
    #     #input();
    print("識別單詞個數:",len(word_list));

    word_convert_xml(word_list,'test.xml');
    print("單詞個數:",len(word_list));



if __name__ == "__main__":
    main();

pdf文件

分離出的圖片:

 
效果:

 對照PDF,效果還是OK的

這裏就會不斷的去識別pdf切割出的圖片

經過處理後的xml

導入到單詞本中:
 

這裏還有衆多BUG,就不改了,湊合用,大概80%的成功率已經可以了  
後續發現老師發來的pdf竟然還有斜着的...老師他們用的這掃描儀也不行阿。。。 辣雞

這也就是爲啥這裏只識別了一個nt,

我認爲好好使用一下百度的ocr接口是可以完全識別這種斜的,而且在加上正則,我估計會有至少99%的正確率
我寫的demo就留給大家進行二次開發把,我python代碼水平比較差python基本上沒有學過,代碼結構和變量命名規則極其不規範~不過也罷啦,我本身就只是拿python當成一種工具使用而已 .爲了100天的考試[解放]加油!!!!!!!!!!!!!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章