#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
日本語テキスト解析プログラム
【機能】
(1) ファイル内のテキスト全体について,
・句点「。」と読点「、」および「,」の出現数
・一文あたりの平均読点数
を求める。
(2) MeCab を用いて形態素解析を行い,
・係助詞「は」の出現数
・その直後に読点がくる確率
を求める。
(3) 係助詞「は」の直後に読点がある場合とない場合で,
・その文の平均文字数
・その文の平均読点数
を求める。
※実行例: python japanese_text_analyzer.py input.txt
"""
import MeCab
import argparse
def analyze_text(text):
# (1) 句点と読点の総数、及び一文あたりの読点数
total_period = text.count("。")
# 読点は「、」と「,」の両方に対応
total_comma = text.count("、") + text.count(",")
# 文章を「。」で分割して文単位にする(文末の句点を補完)
sentences = []
for s in text.split("。"):
s = s.strip()
if s:
sentences.append(s + "。")
num_sentences = len(sentences)
avg_comma_per_sentence = total_comma / num_sentences if num_sentences > 0 else 0
# (2) および (3) の解析用に、形態素解析器を初期化
tagger = MeCab.Tagger()
# 係助詞「は」についての統計
total_ha_occurrences = 0 # 「は」の出現回数(係助詞として)
ha_followed_by_comma = 0 # 「は」の直後に読点がある回数
# (3) 用の文ごとの集計
groupA_sentences = [] # 「は」の直後に読点がある場合を含む文
groupB_sentences = [] # 「は」の直後に読点がない場合を含む文
# 各文ごとに形態素解析を実施して処理する
for sentence in sentences:
# MeCab で形態素解析(各文を対象)
node = tagger.parseToNode(sentence)
tokens = []
while node:
# BOS/EOS ノードは除外
if node.stat in (MeCab.MECAB_BOS_NODE, MeCab.MECAB_EOS_NODE):
node = node.next
continue
# node.feature は「品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音」などの情報
features = node.feature.split(",")
pos = features[0] # 例:"助詞"
pos_detail1 = features[1] # 例:"係助詞"(係助詞ならこの値)
# 原形は features[6] だが、情報がない場合もあるので、surface を利用する
base = features[6] if len(features) > 6 else node.surface
tokens.append({
'surface': node.surface,
'pos': pos,
'pos_detail1': pos_detail1,
'base': base
})
node = node.next
# 各文中の「は」に関して、直後のトークンが読点「、」または「,」かどうかをチェック
sentence_has_ha_followed_comma = False
sentence_has_ha_not_followed_comma = False
for i, token in enumerate(tokens):
# 係助詞としての「は」を対象にする
if token['surface'] == "は" and token['pos'] == "助詞" and token['pos_detail1'] == "係助詞":
total_ha_occurrences += 1
# 直後のトークンが存在するかどうかをチェック
if i + 1 < len(tokens):
next_token = tokens[i + 1]
if next_token['surface'] in ("、", ","):
ha_followed_by_comma += 1
sentence_has_ha_followed_comma = True
else:
sentence_has_ha_not_followed_comma = True
else:
# 直後にトークンがなければ「読点なし」と判断
sentence_has_ha_not_followed_comma = True
# (3) の集計対象として文をグループ分け(※文中に複数の「は」がある場合,
# 直後に読点がある場合とない場合の両方に該当する可能性があります)
if sentence_has_ha_followed_comma:
groupA_sentences.append(sentence)
if sentence_has_ha_not_followed_comma:
groupB_sentences.append(sentence)
# (2) 「は」の直後に読点が来る確率
prob_ha_comma = ha_followed_by_comma / total_ha_occurrences if total_ha_occurrences > 0 else 0
# (3) グループごとの文の平均文字数と平均読点数を計算する関数
def average_metrics(sent_list):
total_chars = 0
total_commas_in_sent = 0
for s in sent_list:
total_chars += len(s)
total_commas_in_sent += s.count("、") + s.count(",")
count = len(sent_list)
if count == 0:
return (0, 0)
return (total_chars / count, total_commas_in_sent / count)
avg_len_groupA, avg_comma_groupA = average_metrics(groupA_sentences)
avg_len_groupB, avg_comma_groupB = average_metrics(groupB_sentences)
# 結果の出力
print("=== 全体の統計 ===")
print("句点「。」の数: ", total_period)
print("読点(「、」と「,」)の数: ", total_comma)
print("一文あたりの平均読点数: {:.2f}".format(avg_comma_per_sentence))
print("")
print("=== 係助詞「は」の統計 ===")
print("係助詞「は」の出現数: ", total_ha_occurrences)
print("直後に読点がくる確率: {:.2f}".format(prob_ha_comma))
print("")
print("=== 係助詞「は」の直後に読点がある文の統計 ===")
print("文数: ", len(groupA_sentences))
print("平均文字数: {:.2f}".format(avg_len_groupA))
print("平均読点数: {:.2f}".format(avg_comma_groupA))
print("")
print("=== 係助詞「は」の直後に読点がない文の統計 ===")
print("文数: ", len(groupB_sentences))
print("平均文字数: {:.2f}".format(avg_len_groupB))
print("平均読点数: {:.2f}".format(avg_comma_groupB))
def main():
# コマンドライン引数で対象のファイルを指定
parser = argparse.ArgumentParser(description="日本語テキスト解析プログラム")
parser.add_argument("file", help="解析対象のテキストファイルパス")
args = parser.parse_args()
# ファイルの読み込み(UTF-8 エンコード前提)
try:
with open(args.file, "r", encoding="utf-8") as f:
text = f.read()
except Exception as e:
print("ファイルの読み込みに失敗しました:", e)
return
analyze_text(text)
if __name__ == "__main__":
main()