天天看點

Python Mecab的使用(Windows)+ PDF的轉換

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

再次執行之後,分詞的問題就解決了。

Python Mecab的使用(Windows)+ PDF的轉換

二、日語注音①

網上搜尋到最多的就是

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/

Python Mecab的使用(Windows)+ PDF的轉換

這三種unidic庫都是可以的,有一定的差別。都挺大的,每一個都大約有四五百M。下載下傳完之後,解壓後把以下的檔案手動copy覆寫到unidic庫的dicdir目錄下,目錄沒有的話需要自己建立一個。另外

mecabrc

這個檔案必須要有,可以是空的。

Python Mecab的使用(Windows)+ PDF的轉換

這塊弄完之後就可以正常執行以下指令了。

import MeCab

text = "私は張ですが、また明日想像指定です"
mecab_tagger = MeCab.Tagger("-chasen")
print(mecab_tagger.parse(text))
           
Python Mecab的使用(Windows)+ PDF的轉換

二、日語注音②

之後也了解了

ipadic

這個庫,使用這個庫貌似也能達到相同的效果。

首先也需要安裝:

  • pip install ipadic

安裝之後字典自動下載下傳了,大約45M左右,比較小巧。

接着使用下面的代碼就可以了:

import ipadic

text = "私は張ですが、また明日想像指定です"
mecab_tagger = MeCab.Tagger(ipadic.MECAB_ARGS)
print(mecab_tagger.parse(text))
           
Python Mecab的使用(Windows)+ PDF的轉換

然後配合

jaconv

庫,将每個單詞的讀音轉為 平假名就完成了注音的功能。安裝指令:

  • pip install jaconv

詳細使用請參照官網。

但是這個程式如果用

pyinstaller

打包之後又會提示找不到字典目錄的情況, 提示的目錄完全看不懂是哪兒,是以修改了ipadic.py的源碼:

第9行:

_curdir = os.path.dirname(__file__)

改為了第10行:

_curdir = os.getcwd()

Python Mecab的使用(Windows)+ PDF的轉換

這樣改了之後,基礎路徑就會變為 檔案運作時的路徑,是以隻需要把

dicdir

這個目錄copy到入口檔案的同級目錄下就可以了,也友善更新字典:

Python Mecab的使用(Windows)+ PDF的轉換

三、文字轉PDF

網上倒是有不少關于PDF轉換的庫,挑來挑去最終選擇了

pdfkit

這個庫,理由是支援保留html樣式轉pdf。

試了好幾種轉換的庫,主要是想保留,日語注音後的html效果,貌似隻有

pdfkit

支援。

Python Mecab的使用(Windows)+ PDF的轉換

首先使用以下指令安裝

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:

Python Mecab的使用(Windows)+ 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("請輸入任意鍵結束...")
           

以上就是我本次想要分享的内容,歡迎大家留言探讨。