Skip to content

Instantly share code, notes, and snippets.

@tsukumijima
Last active October 3, 2020 01:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tsukumijima/9229557ea156a6dc6c675d0829a07d47 to your computer and use it in GitHub Desktop.
Save tsukumijima/9229557ea156a6dc6c675d0829a07d47 to your computer and use it in GitHub Desktop.
過去ログの XML からニコニコ実況にコメントしたユーザー ID と総ユーザー数、コメント回数の平均などを算出するツール
# import
import argparse
import chardet
import os
import re
import statistics
import sys
import xmltodict
import matplotlib.pyplot as plt
from collections import OrderedDict
from pprint import pprint
def main():
# 引数を設定・取得
parser = argparse.ArgumentParser(description = '', formatter_class = argparse.RawTextHelpFormatter)
parser.add_argument('InputFile', help = 'InputXML')
args = parser.parse_args()
# 入力 XML
xml_file = args.InputFile
print()
# ファイル読み込み
with open(xml_file, mode = 'rb') as fp:
# エンコード判定
xml_binary = fp.read()
encoding = chardet.detect(xml_binary)
# 判定した文字エンコードでデコード
xml = xml_binary.decode(encoding['encoding'])
# xml ヘッダをつける
if '<?xml version="1.0"' not in xml:
xml = '<?xml version="1.0"?>\n<thread>\n' + xml + '\n</thread>'
# 不正な xml になっていることがあるので整形
xml = xml.replace('chatthread', 'chat thread')
xml = re.sub(r'([^=]")([^> ])', r'\1 \2', xml)
# xml を解析
nicojk_comment = xmltodict.parse(xml)['thread']['chat']
# ユーザー ID を確認する OrderedDict
nicojk_users = OrderedDict()
# コメントごとに回す
for nicojk_chat in nicojk_comment:
# ユーザー ID が dict 内に存在する
if '@user_id' in nicojk_chat:
# そのユーザー ID のキーが存在しない
if nicojk_chat['@user_id'] not in nicojk_users:
# 新しくキーを作成
# nicojk_users[nicojk_chat['@user_id']] = nicojk_chat
nicojk_users[nicojk_chat['@user_id']] = OrderedDict(nicojk_chat)
nicojk_users[nicojk_chat['@user_id']]['@premium'] = '@premium' in nicojk_chat
nicojk_users[nicojk_chat['@user_id']]['name'] = nicojk_chat['@user_id']
nicojk_users[nicojk_chat['@user_id']]['count'] = 1
# すでにキーが存在する
else:
# カウントを加算
nicojk_users[nicojk_chat['@user_id']]['count'] += 1
# 計算
nicojk_comment_count = []
nicojk_premium_count = 0
for nicojk_user in nicojk_users.values():
# コメント数のみの list を作成
nicojk_comment_count.append(nicojk_user['count'])
# プレミアム会員数をカウント
if nicojk_user['@premium'] == True:
nicojk_premium_count += 1
# 出力
print('ユーザー ID: ' + str(nicojk_user['name']) + ' コメント回数: ' + str(nicojk_user['count']) + ' プレミアム: ' + str(nicojk_user['@premium']))
# 総コメントユーザー数
nicojk_users_count = len(nicojk_users)
# うちプレミアム会員の割合
nicojk_premium_percentage = round(nicojk_premium_count / nicojk_users_count * 100, 2)
# 平均値・中央値を取得
nicojk_comment_count_mean = round(statistics.mean(nicojk_comment_count), 2) # 平均値
nicojk_comment_count_median = round(statistics.median(nicojk_comment_count), 2) # 中央値
# 出力
print()
print('総コメントユーザー数 : ' + str(nicojk_users_count) + ' 人')
print(' うちプレミアム会員 : ' + str(nicojk_premium_count) + ' 人 (' + str(nicojk_premium_percentage) + '%)')
print('コメント回数の平均値 : ' + str(nicojk_comment_count_mean) + ' 回')
print('コメント回数の中央値 : ' + str(nicojk_comment_count_median) + ' 回')
print('コメント回数の最大値 : ' + str(max(nicojk_comment_count)) + ' 回')
print('コメント回数の最小値 : ' + str(min(nicojk_comment_count)) + ' 回')
print()
# matplotlib
plt.hist(nicojk_comment_count, 200, (0, 200), color='c')
plt.xlabel('Number of comments', fontsize=17)
plt.ylabel('Number of users', fontsize=17)
plt.tick_params(labelsize=12)
plt.grid(True)
plt.show()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment