NNDD で重複取得されたコメントを削除するスクリプトを作りました
ニコニコ動画ダウンロード&ビデオ再生ソフトの NNDD(v1_27_6) を愛用しているのですが、Player 設定で「コメントを再生のたびに更新する - コメント更新時にローカルに保存済みのコメントに追記」を有効にしていると、NNDD でコメント投稿後に再度メインウィンドウでその動画を再生した際に、コメントが重複して取得されてしまうバグがあるようです。
この時、コメント .xmlファイルでは、NNDD から投稿したコメントの
<packet> <thread ... /> <view_counter ... /> <chat thread="..." no="1" vpos="..." date="..." mail="..." user_id="..." anonymity="...">コメント</chat> (略) <chat thread="..." no="70" vpos="..." date="..." mail="..." user_id="..." anonymity="...">コメント</chat> <chat thread="..." vpos="..." date="..." mail="..." user_id="..." anonymity="...">NNDDからコメント</chat> <chat thread="..." no="1" vpos="..." date="..." mail="..." user_id="..." anonymity="...">コメント</chat> (略) <chat thread="..." no="71" vpos="..." date="..." mail="..." user_id="..." anonymity="...">NNDDからコメント</chat> (略) </packet>
今まではコメントが保存された .xml ファイルを直接編集して、重複箇所を削除していたのですが、めんどうになったので Python スクリプトを作成しました(要 BeautifulSoup)。
このスクリプトは引数に動画が保存してある NNDD フォルダを指定して実行すると、フォルダ内部の全てのコメント .xml ファイルを解析して重複部分があれば削除します。
Usage: python nndd.py [options] NNDD_DIR Options: -b/--backup : backup mode (書き換えたファイルのバックアップ .xml~ を作成する) -s/--speed : high speed mode (CPU をフルに使って解析する) -h/--help : display help (使用法を表示)
ファイル名を nndd.py として、以下のプログラムを保存してください。
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import os import fnmatch import time import getopt from BeautifulSoup import BeautifulStoneSoup # For processing XML backup_mode = False speed_mode = False def valid_xml(path): global backup_mode global speed_mode file_object = open(path, 'r+') try: contents = file_object.read() # BeautifulStoneSoup soup = BeautifulStoneSoup(contents) chat_list = soup('chat') # <chat> last_no = 0 duplications = [] for chat in chat_list: if not chat.has_key('no'): # エラーの原因 duplications.append(str(chat)) continue no = chat['no'] if not no.isdigit(): continue no = int(no) if no <= last_no: duplications.append(str(chat)) continue last_no = no # high-speed mode off if not speed_mode: time.sleep(0.01) if len(duplications) > 0: # 重複あり # backup mode on if backup_mode: try: backup_file = open(path + '~', 'w') backup_file.write(contents) finally: backup_file.close() # 重複箇所を削除する for dup in duplications: contents = contents.replace(' ' + dup + '\n', '', 1) # XML ファイルの更新 file_object.seek(0) file_object.write(contents) file_object.truncate() print ' rewrited!' finally: file_object.close() def all_files(root, patterns='*', single_level=False, yield_folders=False): # セミコロンで区切られた文字列からパターンを展開してリストにする patterns = patterns.split(';') for path, subdirs, files in os.walk(root): if yield_folders: files.extend(subdirs) files.sort() for name in files: for pattern in patterns: if fnmatch.fnmatch(name, pattern): yield os.path.join(path, name) break if single_level: break def valid_nndd(nndd_dir): # |dir|以下に含まれる .xml ファイルパスを取得 for path in all_files(nndd_dir, '*].xml'): # [Owner].xml と [ThumbInfo].xml ファイルを無視 if path.endswith('[Owner].xml') or path.endswith('[ThumbInfo].xml'): continue print path valid_xml(path) def usage(): print 'Usage:' print ' python nndd.py [options] NNDD_DIR' print ' -b/--backup : backup mode' print ' -s/--speed : high speed mode' print ' -h/--help : display help' def main(): global backup_mode global speed_mode if len(sys.argv) >= 2: # オプションを解析 try: opts, args = getopt.getopt(sys.argv[1:], 'bsh', ['backup', 'speed', 'help']) except getopt.GetoptError, err: # ヘルプメッセージを出力して終了 print str(err) usage() sys.exit(2) for opt, arg in opts: if opt in ('-b', '--backup'): # バックアップモード backup_mode = True elif opt in ('-s', '--speed'): # ハイスピードモード speed_mode = True elif opt in ('-h', '--help'): # ヘルプ表示 usage() sys.exit() else: assert False, 'unhandled option' nndd_dir = args[0] valid_nndd(nndd_dir) if __name__ == '__main__': main()
Windows で Python を使用する方法(パス設定等)はこちらを参考に。
NNDD フォルダは、Windows であれば /Users/アカウント名/Documents/NNDD にあります。