iT邦幫忙

0

[Python] PyPDF2+PYTSS3 將中文PDF轉成MP3存檔, 中文亂碼問題

  • 分享至 

  • xImage

想把手邊的電子書,大部分中文,簡體繁體都有,參考網路範例寫了一個
但是英文沒問題,中文印出來就已經變成亂碼,有用UTF-8編碼但是還是一樣,求教一下各位高手 謝謝你的幫忙

import pyttsx3
from PyPDF2 import PdfFileReader

def getPdfContent(filename):
    pdf = PdfFileReader(open(filename, "rb"))
    content = ""
    for i in range(0, pdf.getNumPages()):
        pageObj = pdf.getPage(i)
        extractedText = pageObj.extractText()
        content += extractedText + "\n"
        
    return content.encode("utf-8", "ignore")

text = getPdfContent('chinese.pdf')
#查出來念中文是哪個機碼ID
zh_voiceid = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_MS_ZH-TW_HANHAN_11.0'
engine= pyttsx3.init()
#設定念中文
engine.setProperty('voice',zh_voiceid) 
#設定語速
rate = engine.getProperty('rate')
print(rate)
engine.setProperty('rate', rate+20)
#印出中文就不行了
#print(text.decode("utf-8"))
engine.save_to_file(text, 'chinese.mp3')
engine.runAndWait()
alien663 iT邦研究生 5 級 ‧ 2023-02-23 17:04:11 檢舉
根據我自己幾年前的研究,PDFMiner在取中文的效果最佳,但仍會有部分字是顯示`(cid:1234)`這種情況,一旦遇到特殊文字或是數學符號,更有可能整篇PDF全部陣亡,可謂狀況層出不窮。
近幾年是否有更好的做法我不得而知,等其他大神救援吧。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

1
ccutmis
iT邦高手 2 級 ‧ 2023-02-23 18:29:57
最佳解答

我只是把 return content.encode("utf-8", "ignore") 改成 return content 就能運作了,您試試看...

import pyttsx3
from PyPDF2 import PdfFileReader

def getPdfContent(filename):
    pdf = PdfFileReader(open(filename, "rb"))
    content = ""
    for i in range(0, pdf.getNumPages()):
        pageObj = pdf.getPage(i)
        extractedText = pageObj.extractText()
        content += extractedText + "\n"
        
    return content

pdf_file = "中文測試.pdf"

text = getPdfContent(pdf_file)
#查出來念中文是哪個機碼ID
zh_voiceid = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_MS_ZH-TW_HANHAN_11.0'
engine= pyttsx3.init()
#設定念中文
engine.setProperty('voice',zh_voiceid) 
#設定語速
rate = engine.getProperty('rate')
print(rate)
engine.setProperty('rate', rate+20)
#印出中文就不行了
#print(text.decode("utf-8"))
engine.save_to_file(text, pdf_file[:-4]+'.mp3')
engine.runAndWait()

註: 我用的測試檔是把樓主的本文貼到 google文件,下載轉存為 pdf,可以轉成mp3正確讀出內容。


感謝 邦友淺水員 分享 pdf 的特異功能,爬了一晚感覺這技術應該不是資質平平的我能短時間攻克的,先把它記錄下來,日後得閒再來燒腦子... 這邊先以 OCR 方式給樓主的問題作一個建議,以下是用 淺水員 分享的兩個 pdf 檔測試過能正常轉出文字檔的範例:

import pytesseract
from PIL import Image
import os
import fitz

def img2txt(img_src,lang='chi_tra',ocr_exe_path=r"C:\Tesseract-OCR\tesseract.exe"):
    pytesseract.pytesseract.tesseract_cmd = ocr_exe_path
    img = Image.open(img_src)
    return pytesseract.image_to_string(img, lang=lang)

def pdf2imgs(pdf_src):
    zoom_x, zoom_y= 2.0, 2.0
    mat=fitz.Matrix(zoom_x,zoom_y)
    if pdf_src.find('/')!=-1:
        filename=pdf_src.split('/')[-1]
    else:
        filename=pdf_src.split('\\')[-1]
    foldername=filename.split(".")[0]
    #if not os.path.exists('./img'):
    #    os.makedirs('./img')
    if not os.path.exists('./img/'+foldername):
        os.makedirs('./img/'+foldername)
    doc=fitz.open(pdf_src)
    output_ls = []
    for page in doc:
        pix=page.get_pixmap(matrix=mat)
        j=str(page.number+1).rjust(3,'0')
        output_ls.append("./img/%s/page_%s.png" % (foldername,j))
        pix.save("./img/%s/page_%s.png" % (foldername,j))
    return output_ls

def pdf_to_txt_by_ocr(pdf_src):
    img_ls = pdf2imgs(pdf_src)
    txt = ''
    for i in img_ls:
        txt += img2txt(i)
    with open(pdf_src[:-4]+'.txt','w+',encoding='utf-8') as f:
        f.write(txt)

def main():
    pdf_file = r'pdf/fake-unicode.pdf'
    pdf_to_txt_by_ocr(pdf_file)
    pdf_file = r'pdf/noToUnicode.pdf'
    pdf_to_txt_by_ocr(pdf_file)

if __name__ == "__main__":
    main()

orc執行檔的路徑請依您安裝 tesseract 的路徑作修改,我是把它安裝在C:\根目錄

ocr_exe_path=r"C:\Tesseract-OCR\tesseract.exe"

測試的Python版本為 3.7.9

需要安裝的套件如下 :

pip install Pillow opencv-python pytesseract PyMuPDF

OCR設置部份請參考這篇邦友的文章:
https://ithelp.ithome.com.tw/articles/10227263

註:轉文字檔是能轉了但有精確度的問題。

看更多先前的回應...收起先前的回應...
lalelee iT邦新手 4 級 ‧ 2023-02-24 08:08:51 檢舉

嗚嗚~ 我一開始用的就是沒有encode過的, 所以看起來我的PDF檔可能都是有問題不是純PDF, 這個不知道要怎麼查了 @@

ccutmis iT邦高手 2 級 ‧ 2023-02-24 08:34:50 檢舉

可能就像樓上的alien663邦友說的那樣 還是你能給我一個轉不出來的中文pdf範本檔(用站內私訊給 google雲端硬碟的檔案聯結) 假日我再試試看?

淺水員 iT邦大師 6 級 ‧ 2023-02-24 16:40:39 檢舉

PDF檔的文字複製後再貼上到任何一個地方,文字會一樣嗎?
還是會變亂碼?

淺水員 iT邦大師 6 級 ‧ 2023-02-24 17:05:50 檢舉

提供兩個會有問題的 PDF 實驗:

ccutmis iT邦高手 2 級 ‧ 2023-02-24 17:14:31 檢舉

沒記錯的話若是手動複制pdf檔的文字,用notepad++開新檔貼上應該是ok吧? 編碼的部份在copy---paste中間os會自動轉換處理,貼到notepad++時已經是unicode繁中語系而不是Big5或GB2312了


謝謝分享,回家再來測試~!

ccutmis iT邦高手 2 級 ‧ 2023-02-24 19:04:34 檢舉

PDF檔的文字複製後再貼上到任何一個地方,文字會一樣嗎?
還是會變亂碼?

提供兩個會有問題的 PDF 實驗:

noToUnicode.pdf:因為缺少部分資訊,複製貼上會是亂碼
fake-unicode.pdf:複製貼上後會變成另外一串文字的PDF


新年快樂!~ 測試結果如下:

  • noToUnicode.pdf
    內容可讀,複制貼到文字檔是亂碼。
 
0!)(-+,'
12$3/
+'
0#"!&%
	.*
  • fake-unicode.pdf
    內容顯示的是 "月落烏啼霜滿天,江楓漁火對愁眠",複制貼到文字檔卻是 "但使龍城飛將在,不教胡馬度陰山"

真神奇QQ,請問大師這是怎麼辦到的,有相關的學習資源可以推薦嗎,感謝先~

淺水員 iT邦大師 6 級 ‧ 2023-02-24 19:22:16 檢舉

原理大概就是,向量圖(肉眼看到的字)與對應的 charcode 資訊遺失或是被變更了。
第一份是遺失這份資訊,而第二份是刻意變更過。
至於資源,我以前沒特別整理,但另外類似的關鍵字有「字型防爬」這樣的技術,雖然說那是用在網頁上的,不過原理很類似

ccutmis iT邦高手 2 級 ‧ 2023-02-24 19:30:01 檢舉

好的,我再依關鍵字去爬文,感謝~~
/images/emoticon/emoticon82.gif

淺水員 iT邦大師 6 級 ‧ 2023-02-24 19:34:35 檢舉

通常第一種比較常見
因為有些 pdf 函式庫會漏掉寫入 unicode 跟向量圖的對應表
反正這不影響檢視與列印,只是複製貼上會有問題而已

ccutmis iT邦高手 2 級 ‧ 2023-02-25 00:36:28 檢舉

淺水員大師 我投降了~ 難度跟用Python套件不是同等級的,暫時先用OCR寫的範例給樓主一個膠帶,謝謝您支援的範例檔...

lalelee iT邦新手 4 級 ‧ 2023-02-26 09:18:17 檢舉

感謝ccutmis 和 淺水員大大, 你們對Python的熱愛和經驗令小弟佩服, 我等一下試試OCR的做法, 另外附上讀出來有問題的中文檔, 基本上幾乎是全部有的是檢體有的是繁體以下附上連結:
链接:https://pan.baidu.com/s/1WUFiogTxE5TpmDf5qf_iIg
提取码:pnmg

感謝再三
P.S: 這篇Google已經置頂了 XD

lalelee iT邦新手 4 級 ‧ 2023-02-26 10:22:03 檢舉

試了一陣子,有成功產出png檔, 但是就會報錯:

  File "C:\Python38\lib\subprocess.py", line 829, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "C:\Python38\lib\subprocess.py", line 1278, in _execute_child    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
PermissionError: [WinError 5] 存取被拒。

有試過用系統管理員權限去跑也是不行,不論是在VS Code或是單獨開都不行,查了一下StackOverflow 也是眾說紛紜@@

目前卡住了...

ccutmis iT邦高手 2 級 ‧ 2023-02-26 17:49:12 檢舉

lalelee

附上連結...略

我這邊顯示 "無法連上這個網站" 可能對岸又封鎖中華電信了,能否給個mega的測式連結,謝謝~

PermissionError: [WinError 5] 存取被拒。

以我給你參考的範例來說,只要是正確的打開方式應該是不會有這問題,但是您給的資訊太少沒辦法判斷,存取被拒可能是: 系統登入帳戶執行的權限不足,或是你存取了受系統保護的路徑,我舉個例子,如果你存取的路徑是C:\根目錄,那個系統可能就會擋,或是C:\Users\裡面某些路徑可能也會,你可以試試這樣做:

  1. 首先是Python安裝路徑安裝在 "C:\Python38"
  2. 前面提到的 OCR程式 安裝在 "C:\Tesseract-OCR"
  3. 要測試的資料夾就在 C:\ 新增一個資料夾自行命名,例如: "C:\test_pdf_to_txt" 然後在裡面新建一個 "main.py" 把上面的範例複制貼上,參數修改好就能測試了,理論上是沒那麼複雜,您再試試看...祝好運!

註: 我在安裝 Tesseract-OCR時,當進行到步驟"Choose Components",那裡面的 "[ + ] Additional language data(download)" 點進去勾選"Chinese開頭的四個選項",然後繼續進行安裝,經windows沙箱測試安裝完成後,就可以直接跑 main.py了,輸出png跟文字檔都正常(文字檔跟pdf檔放在一起)

lalelee iT邦新手 4 級 ‧ 2023-02-27 22:27:43 檢舉

C大真的感謝你一直回答問題^^ 我剛找到原因了, 我的Tesseract-OCR 沒有放到執行檔, 我本來是r"C:\Tesseract-OCR" 要加上tesseract.exe XD 現在可以成功OCR出來了!
再來只要轉成MP3 就行了, 中文真是麻煩 XD

ccutmis iT邦高手 2 級 ‧ 2023-02-28 00:26:39 檢舉

/images/emoticon/emoticon10.gif

0
kaonick
iT邦新手 5 級 ‧ 2023-03-01 12:23:38

因為沒辦法控制pdf用什麼字型,所以我的方法是直接把pdf轉成image,然後再載入,就不會受字型影響了!

lalelee iT邦新手 4 級 ‧ 2023-03-01 13:58:33 檢舉

就是上面C大說的用OCR的辦法嗎 ?

kaonick iT邦新手 5 級 ‧ 2023-03-02 10:18:58 檢舉

差不多,只是OCR要選好一點,Tesseract免錢的,辨識效果差了一點。
若是能夠找到embed字型,就比較好,直接讀取內文應該是比較好的解決方法,可以參考:
How do I embed fonts in an existing PDF?

我要發表回答

立即登入回答