Skip to content

Instantly share code, notes, and snippets.

@kujirahand
Last active May 24, 2025 15:12
Show Gist options
  • Save kujirahand/cb811206070506fc4cecee6ff4a62cd3 to your computer and use it in GitHub Desktop.
Save kujirahand/cb811206070506fc4cecee6ff4a62cd3 to your computer and use it in GitHub Desktop.
形態素解析を利用した簡単な文章の校正ツール
"""文章の校正ツール"""
import sys
from janome.tokenizer import Tokenizer
# 形態素解析のためのTokenizerのインスタンスを生成
tokenizer = Tokenizer()
# 接続詞の一覧
setuzokusi = set()
def check_text(text):
"""テキストをチェックする"""
errors = []
# 改行コードを統一する
text = text.replace("\r\n", "\n").replace("\r", "\n")
text = text.replace("\n", " ¶ ") # 行数をカウントするため「 ¶」を挿入
text += " ¶ "
# 形態素解析してトークンに分割
tokens = []
for t in tokenizer.tokenize(text):
pos = t.part_of_speech
# 接続詞を抽出
if pos.startswith(("接続詞")):
setuzokusi.add(t.surface)
tokens.append(t.surface)
# 一文の長さをチェックする
errors += check_length(tokens)
# 接続詞の繰り返しを検出
print("[INFO] 接続詞の繰り返しをチェックしています...", setuzokusi)
for word in setuzokusi:
errors += check_repeat(tokens, word, 8)
errors.sort(key=lambda x: int(x.split(":")[0])) # 行番号でソート
if len(errors) == 0:
print("[OK] 特に問題は見つかりませんでした。")
else:
for error in errors:
print(f"[ERROR] {error}")
return errors
def check_length(tokens: list[str], max_length: int = 100):
"""一文の長さをチェックする"""
errors = []
s = ""
line_no = 1
for t in tokens:
if t in ["¶", "。"]:
s_len = len(s)
if s_len > max_length:
errors.append(f"{line_no}: 一文が長すぎます({s_len}文字)\n" + \
f" - {s[:30]}…")
s = ""
if t == "¶":
line_no += 1
continue
s += t
return errors
def check_repeat(tokens: list[str], word: str, limit: int = 8):
"""繰り返しをチェックする"""
# 近くに同じ接続詞が登場しないかチェック
last_line = 0
last_near = ""
line_no = 1
errors = []
for i, t in enumerate(tokens):
if t == "¶":
line_no += 1
continue
if t != word:
continue
if last_line == 0:
last_line = line_no
elif line_no - last_line <= limit:
near = "".join(tokens[i:i+10])
errors.append(
f"{line_no}:「{word}」が連続しています\n" + \
f" -{last_line:4}行目: {last_near}…\n" + \
f" -{line_no:4}行目: {near}…")
last_line = line_no
last_near = "".join(tokens[i: i+10])
return errors
def check_file(file_path):
"""ファイルをチェックする"""
with open(file_path, 'r', encoding='utf-8') as file:
text = file.read()
# テキストをチェックする
return check_text(text)
if __name__ == "__main__":
if len(sys.argv) == 2:
# コマンドライン引数でファイル名が指定された場合
check_file(sys.argv[1])
else:
print("使い方: python proofreading.py [ファイル名]")
@kujirahand
Copy link
Author

kujirahand commented May 24, 2025

実行するまえに、ターミナルでpip install TkEasyGUIを実行して、GUIライブラリをインストールします。

そして、上記のプログラム「proofreading.py」と以下のプログラム「gui_proofreading.py」を同じフォルダに配置してから実行してください。

import TkEasyGUI as eg
import proofreading

layout = [
    [eg.Text("Text:")],
    [eg.Multiline(size=(80, 8), key="text", expand_x=True)],
    [eg.Button("Check")],
    [eg.Text("Results:")],
    [eg.Multiline(size=(80, 8), key="results", expand_x=True, expand_y=True)],
]
window = eg.Window("Proofreading Tool", layout, resizable=True)
while window.is_alive():
    event, values = window.read()
    if event == "Exit" or event is None:
        break
    if event == "Check":
        text = values["text"]
        # ここで形態素解析やチェックを行う
        errors = proofreading.check_text(text)
        results = window["results"]
        results.update("")
        for error in errors:
            lines = error.split("\n")
            for i, line in enumerate(lines):
                if i == 0:
                    results.print(f"[ERROR] {line}", "red")
                else:
                    results.print(line, "blue")
        results.print("ok", "green")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment