Python Mecab的使用(Windows)+ PDF的轉換
最近最近做了個翻譯網頁,主要是為了學日語用。但是就日語注音這一塊兒很難搞,嘗試了多種方法,都沒成功。最後采用還是選擇了用Python+Mecab的方向去實作這一功能。
一、日語分詞
我使用了以下指令安裝了
mecab-python3
- pip3 install mecab-python3
然後執行了以下代碼:
import MeCab
text = "天気がいいから、散歩しましょう"
mecab_tagger = MeCab.Tagger("-Owakati")
print(mecab_tagger.parse(text))
我得到了以下的錯誤:
Traceback (most recent call last):
File "E:\Python env projects\JaToKana\venv\lib\site-packages\MeCab\__init__.py", line 133, in __init__
super(Tagger, self).__init__(args)
RuntimeError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "E:/Python env projects/JaToKana/main.py", line 4, in <module>
mecab_tagger = MeCab.Tagger("-Owakati")
File "E:\Python env projects\JaToKana\venv\lib\site-packages\MeCab\__init__.py", line 135, in __init__
raise RuntimeError(error_info(rawargs)) from ee
RuntimeError:
----------------------------------------------------------
Failed initializing MeCab. Please see the README for possible solutions:
https://github.com/SamuraiT/mecab-python3#common-issues
If you are still having trouble, please file an issue here, and include the
ERROR DETAILS below:
https://github.com/SamuraiT/mecab-python3/issues
issueを英語で書く必要はありません。
------------------- ERROR DETAILS ------------------------
arguments: -Owakati
[ifs] no such file or directory: c:\mecab\mecabrc
----------------------------------------------------------
網上百度之後發現,這個錯誤是由于缺少詞庫導緻的,需要使用以下指令安裝
unidic-lite
詞庫依賴。
- pip install unidic-lite
再次執行之後,分詞的問題就解決了。
二、日語注音①
網上搜尋到最多的就是
mecab_tagger = MeCab.Tagger("-Ochasen")
, 但是經過個人嘗試,以及官方說明,正确的寫法為
MeCab.Tagger("-chasen")
。
不出意外會提示你找不到 xxx/dicdic/目錄下的mecabrc檔案。
使用
-chasen
參數需要安裝以下的包,
- pip install unidic
但是安裝之後,并不會像
unidic-lite
庫安裝時那樣自動下載下傳字典庫, 你需要執行以下指令下載下傳字典:
- python -m unidic download
但是發現沒法下載下傳,好像下載下傳位址已經沒有了還是中國大陸沒法通路的原因吧。是以一番查找下去以下的網址下載下傳了官方的字典庫:
https://clrd.ninjal.ac.jp/unidic/
這三種unidic庫都是可以的,有一定的差別。都挺大的,每一個都大約有四五百M。下載下傳完之後,解壓後把以下的檔案手動copy覆寫到unidic庫的dicdir目錄下,目錄沒有的話需要自己建立一個。另外
mecabrc
這個檔案必須要有,可以是空的。
這塊弄完之後就可以正常執行以下指令了。
import MeCab
text = "私は張ですが、また明日想像指定です"
mecab_tagger = MeCab.Tagger("-chasen")
print(mecab_tagger.parse(text))
二、日語注音②
之後也了解了
ipadic
這個庫,使用這個庫貌似也能達到相同的效果。
首先也需要安裝:
- pip install ipadic
安裝之後字典自動下載下傳了,大約45M左右,比較小巧。
接着使用下面的代碼就可以了:
import ipadic
text = "私は張ですが、また明日想像指定です"
mecab_tagger = MeCab.Tagger(ipadic.MECAB_ARGS)
print(mecab_tagger.parse(text))
然後配合
jaconv
庫,将每個單詞的讀音轉為 平假名就完成了注音的功能。安裝指令:
- pip install jaconv
詳細使用請參照官網。
但是這個程式如果用
pyinstaller
打包之後又會提示找不到字典目錄的情況, 提示的目錄完全看不懂是哪兒,是以修改了ipadic.py的源碼:
第9行:
_curdir = os.path.dirname(__file__)
改為了第10行:
_curdir = os.getcwd()
這樣改了之後,基礎路徑就會變為 檔案運作時的路徑,是以隻需要把
dicdir
這個目錄copy到入口檔案的同級目錄下就可以了,也友善更新字典:
三、文字轉PDF
網上倒是有不少關于PDF轉換的庫,挑來挑去最終選擇了
pdfkit
這個庫,理由是支援保留html樣式轉pdf。
試了好幾種轉換的庫,主要是想保留,日語注音後的html效果,貌似隻有
pdfkit
支援。
首先使用以下指令安裝
pdfkit
庫:
- pip install pdfkit
這個庫對于PDF的轉換是依賴于第三方軟體
wkhtmltopdf
的,需要的朋友可以從這裡下載下傳:https://download.csdn.net/download/qq_36991535/87213206
解壓之後放入項目中,然後運作以下的代碼:
path_wk = r"wkhtmltox\bin\wkhtmltopdf.exe"
pdfkit_config = pdfkit.configuration(wkhtmltopdf=path_wk)
text = "<ruby>天気<rt>てんき</rt></ruby>がいいから、<ruby>散歩<rt>さんぽ</rt></ruby>しましょう。"
options = {
'encoding': "utf-8",
'page-size': 'A4',
# 'margin-top': '0mm',
# 'margin-right': '0mm',
# 'margin-bottom': '0mm',
# 'margin-left': '0mm'
}
pdfkit.from_string(text, "test01.pdf", configuration=pdfkit_config, options=options)
你會得到以下的PDF:
四、最後的代碼
最後分享以下我這邊最終封裝的一些代碼,其中word轉pdf用的
mammoth
庫,pdf轉word文檔用的
pdf2docx
這個庫。
完整的程式請從這裡下載下傳: https://download.csdn.net/download/qq_36991535/87213229
import os
import traceback
import MeCab
import ipadic
import jaconv
import pdfkit
import mammoth
from pdf2docx import Converter
path_wk = r"wkhtmltox\bin\wkhtmltopdf.exe"
pdfkit_config = pdfkit.configuration(wkhtmltopdf=path_wk)
mecab = MeCab.Tagger(ipadic.MECAB_ARGS)
def get_kana(text):
"""
将text全部轉為平假名
:param text:
:return:
"""
result = mecab.parse(text)
words_arr = result.split("\n")
kana_result = ""
for word in words_arr:
if word == "EOS":
break
key = word.split("\t")[0]
mean = word.split("\t")[1].split(",")
kana = mean[len(mean) - 2]
if kana == "*" or kana == key:
kana_result = f"{kana_result}{key}"
else:
kana_result = f"{kana_result}{jaconv.kata2hira(kana)}"
return kana_result
def get_kata(text):
"""
将text全部轉為片假名
:param text:
:return:
"""
result = mecab.parse(text)
# print(result)
words_arr = result.split("\n")
hira_result = ""
for word in words_arr:
if word == "EOS":
break
key = word.split("\t")[0]
mean = word.split("\t")[1].split(",")
kana = mean[len(mean) - 2]
if kana == "*" or kana == key:
hira_result = f"{hira_result}{key}"
else:
hira_result = f"{hira_result}{jaconv.hira2kata(kana)}"
return hira_result
def get_words_dict(text):
"""
分析text文本中的日語單詞,傳回單詞的平片假名,以及詞性等資訊
:param text:
:return:
"""
result_dict = {}
result = mecab.parse(text)
words_arr = result.split("\n")
for word in words_arr:
if word == "EOS":
break
key = word.split("\t")[0]
if key not in result_dict:
mean = word.split("\t")[1].split(",")
hira = mean[len(mean) - 2]
if hira == "*" or hira == key:
result_dict[key] = {
"kana": "",
"hira": "",
"category": ""
}
else:
kana = jaconv.kata2hira(hira)
category = ",".join(mean[:-3]).replace(",*", "").rstrip(",")
result_dict[key] = {
"kana": kana,
"hira": hira,
"category": category
}
return result_dict
def get_text_with_kana(text):
"""
以漢字詞[注音]的形式傳回text
:param text:
:return:
"""
result = mecab.parse(text)
words_arr = result.split("\n")
kana_result = ""
for word in words_arr:
if word == "EOS":
break
key = word.split("\t")[0]
mean = word.split("\t")[1].split(",")
hira = mean[len(mean) - 2]
if hira == "*" or hira == key:
kana_result = f"{kana_result}{key}"
else:
kana = jaconv.kata2hira(hira)
if key == kana:
kana_result = f"{kana_result}{key}"
else:
kana_result = f"{kana_result}{key}[{kana}] "
return kana_result
def get_html_with_kana(text):
"""
傳回html代碼注音的文本,<ruby>漢字詞<rt>注音</rt></ruby>
:param text:
:return:
"""
result = mecab.parse(text)
words_arr = result.split("\n")
kana_result = ""
for word in words_arr:
if word == "EOS":
break
key = word.split("\t")[0]
mean = word.split("\t")[1].split(",")
hira = mean[len(mean) - 2]
if hira == "*" or hira == key:
kana_result = f"{kana_result}{key}"
else:
kana = jaconv.kata2hira(hira)
if key == kana:
kana_result = f"{kana_result}{key}"
else:
kana_result = f"{kana_result}<ruby>{key}<rt>{kana}</rt></ruby>"
return kana_result
def get_complated_html(text_kana):
"""
将含有日語注音的文本,替換到模闆html中後傳回模闆html代碼
:param text_kana:
:return:
"""
with open("templte_kana.html", mode="r", encoding="utf-8") as f:
html_kana = f.read().replace("#content", text_kana)
return html_kana
def html_file_to_kana_html(html_file, encoding="utf-8"):
"""
日本語html檔案注音,生成帶有注音的html檔案
:param html_file:
:param encoding:
:return:
"""
with open(html_file, mode="r", encoding=encoding) as f:
html_text = f.read()
result_html_file = html_file.replace(".html", "_kana.html")
with open(result_html_file, mode="w", encoding=encoding) as wf:
wf.write(get_html_with_kana(html_text))
def text_with_kana_to_word(text="", outputfile="document.docx"):
"""
将帶有注音的文字轉換成word文檔
:param text:
:param outputfile:
:return:
"""
try:
temp_pdf = "temp.pdf"
if text_to_pdf(text=text, outputfile=temp_pdf):
cv = Converter(temp_pdf)
cv.convert(outputfile, start=0, end=None)
cv.close()
os.remove(temp_pdf)
return True
return False
except:
traceback.print_exc()
return False
def text_to_pdf(text="", outputfile="document.pdf"):
"""
将text文本轉換成PDF,支援html代碼
:param text:
:param outputfile:
:return:
"""
try:
options = {
'encoding': "utf-8",
'page-size': 'A4',
# 'margin-top': '0mm',
# 'margin-right': '0mm',
# 'margin-bottom': '0mm',
# 'margin-left': '0mm'
}
pdfkit.from_string(text, outputfile, configuration=pdfkit_config, options=options)
return True
except:
traceback.print_exc()
return False
def html_to_pdf(html_file, outputfile="document.pdf"):
"""
直接将html檔案轉換為pdf檔案
:param html_file:
:param outputfile:
:return:
"""
options = {
'encoding': "utf-8",
'page-size': 'A4',
# 'margin-top': '0mm',
# 'margin-right': '0mm',
# 'margin-bottom': '0mm',
# 'margin-left': '0mm'
}
pdfkit.from_file(html_file, outputfile, configuration=pdfkit_config, options=options)
def word_to_mark_kana(word_file, output_word_file="output.docx"):
"""
word文檔标注假名,格式會稍微有些變化
:param word_file:
:param output_word_file:
:return:
"""
with open(word_file, "rb") as docx_file:
result = mammoth.convert_to_html(docx_file)
text_kana = get_html_with_kana(result.value)
html_code = get_complated_html(text_kana)
text_with_kana_to_word(html_code, outputfile=output_word_file)
# text_with_kana_to_word(text_kana, outputfile=output_word_file)
def word_to_pdf(word_file, pdf_file):
"""
word文檔轉PDF,會保留格式轉換
:param word_file:
:param pdf_file:
:return:
"""
with open(word_file, "rb") as docx_file:
result = mammoth.convert_to_html(docx_file)
text_to_pdf(result.value, pdf_file)
try:
text = "天気がいいから、散歩しましょう。"
# text = open("test.html", encoding="utf-8").read()
# print(get_kana(text))
# print(get_kata(text))
# print(get_text_with_kana(text))
print(get_html_with_kana(text))
text_to_pdf("<ruby>天気<rt>てんき</rt></ruby>がいいから、<ruby>散歩<rt>さんぽ</rt></ruby>しましょう。", "test01.pdf")
# print(get_words_dict(text))
# text = get_html_with_kana(text)
# html_code = get_complated_html(text)
# text_with_kana_to_word(text, "test.docx")
# print(text)
# html_with_kana_to_word(text)
# html_with_kana_to_pdf(text)
# html_file_to_kana_html("test.html")
# html_to_pdf("test.html", "test.pdf")
# word_to_mark_kana("小班美術教案.docx", output_word_file="小班美術教案.docx")
# word_to_pdf("幼稚園組織與管理名詞解釋題.docx", "幼稚園組織與管理名詞解釋題.pdf")
pass
except:
traceback.print_exc()
# input("請輸入任意鍵結束...")
以上就是我本次想要分享的内容,歡迎大家留言探讨。