ニコニコ動画の再生数、コメント数、マイリス数を定点観測するスクリプト

某氏から「最近日記書いてないですね」と言われたので書きますよー。


とある事情から、ニコニコ動画の特定の動画に関して再生数、コメント数、マイリス数の伸びを観測する必要が生じたため、観測用のスクリプトをでっち上げてみました。

  • 情報の取得には、ニコニコ動画が提供している動画情報取得用 API の getthumbinfo を使います。
  • API の戻りは XML なので、パースしてから欲しい値だけを引っこ抜きます。
  • 結果を mysql に insert します。
  • このスクリプトを、cron で 30分おきに叩きます。


データ永続化用のテーブル

create table counter (
    id int unsigned not null primary key auto_increment,
    video_id varchar(10) not null,
    view_counter int unsigned not null,
    comment_num int unsigned not null,
    mylist_counter int unsigned not null,
    created timestamp  default current_timestamp
);

api/thumbinfo.py

# coding: utf-8
from xml.dom import minidom
import urllib2
import time

class ThumbInfo(object):
    
    def __init__(self, video_id):
        xmlstring = self._getxml_from_nicoapi(video_id)
        self.parsed = minidom.parseString(xmlstring)
        
        view_counter = self._getnodevalue('view_counter')
        self.view_counter = int(view_counter)
        comment_num = self._getnodevalue('comment_num')
        self.comment_num = int(comment_num)
        mylist_counter = self._getnodevalue('mylist_counter')
        self.mylist_counter = int(mylist_counter)
    
    def _getxml_from_nicoapi(self, video_id):
        # この API が連続して呼ばれたときに、ニコニコ API 側に負荷をかけすぎないよう wait をいれておく
        time.sleep(0.1)
        response = urllib2.urlopen('http://www.nicovideo.jp/api/getthumbinfo/%(video_id)s' % locals())
        return response.read()
    
    def _getnodevalue(self, tagname):
        return self.parsed.getElementsByTagName(tagname)[0].childNodes[0].nodeValue


def run(video_id):
    info = ThumbInfo(video_id)
    import MySQLdb
    con = MySQLdb.connect(db='nicovideo', user='nicovideo', passwd='**********')
    cur = con.cursor()
    sql = """
        insert into counter (
            video_id,
            view_counter,
            comment_num,
            mylist_counter
        ) values (
            '%s',
            %s,
            %s,
            %s
        )
    """ % (video_id, info.view_counter, info.comment_num, info.mylist_counter)
    
    cur.execute(sql)
    
    cur.close()
    con.close()

if __name__ == '__main__':
    pass

poll_thumbinfo.py

#!/usr/bin/env python
# coding: utf-8
from api import thumbinfo

def main():
    # RozenkreuzP
    thumbinfo.run('sm3381792') # Dolls
    thumbinfo.run('sm3381726') # Ever
    thumbinfo.run('sm3381632') # Falling Rainbow
    thumbinfo.run('sm3375792') # Falling Rainbow/Ever/Dolls
    thumbinfo.run('sm2227394') # Aurora
    thumbinfo.run('sm2061292') # Higher than Clouds
    thumbinfo.run('sm1914307') # Linkage

if __name__ == '__main__':
    main()

crontab

*/30 * * * * /home/takanori/junks/nicovideo/poll_thumbinfo.py >/dev/null 2>&1


こんな感じで再生数、コメント数、マイリス数がストックされます。

mysql> select * from counter;
+----+-----------+--------------+-------------+----------------+---------------------+
| id | video_id  | view_counter | comment_num | mylist_counter | created             |
+----+-----------+--------------+-------------+----------------+---------------------+
|  1 | sm3381792 |        39731 |        1225 |           1480 | 2009-06-21 03:39:52 | 
|  2 | sm3381792 |        39731 |        1225 |           1480 | 2009-06-21 03:49:38 | 
|  3 | sm3381726 |        22164 |        1252 |            878 | 2009-06-21 03:49:38 | 
|  4 | sm3381632 |         6070 |         238 |            175 | 2009-06-21 03:49:38 | 
|  5 | sm3375792 |         7307 |         370 |            196 | 2009-06-21 03:49:39 | 
|  6 | sm2227394 |        22307 |        1371 |           1148 | 2009-06-21 03:49:39 | 
|  7 | sm2061292 |        17235 |        1056 |            486 | 2009-06-21 03:49:39 | 
|  8 | sm1914307 |       144321 |        7552 |           4860 | 2009-06-21 03:49:39 | 
|  9 | sm3381792 |        39731 |        1225 |           1480 | 2009-06-21 04:00:01 | 
| 10 | sm3381726 |        22164 |        1252 |            878 | 2009-06-21 04:00:01 | 
| 11 | sm3381632 |         6070 |         238 |            175 | 2009-06-21 04:00:01 | 
| 12 | sm3375792 |         7307 |         370 |            196 | 2009-06-21 04:00:02 | 
| 13 | sm2227394 |        22307 |        1371 |           1148 | 2009-06-21 04:00:02 | 
| 14 | sm2061292 |        17235 |        1056 |            486 | 2009-06-21 04:00:02 | 
| 15 | sm1914307 |       144321 |        7552 |           4860 | 2009-06-21 04:00:02 | 
+----+-----------+--------------+-------------+----------------+---------------------+
15 rows in set (0.00 sec)


(2009/06/21 12:17 追記) スクリプトを動かすには、MySQLdb が必要です。ubuntu だと以下のようにしてインストールできます。

$ sudo aptitude install python-mysqldb


(2009/06/21 22:18 追記) いちいちスクリプトを修正するのがめんどいので、動画のIDリストは別ファイルに定義するようにしました。

poll_thumbinfo.py 修正版

#!/usr/bin/env python
# coding: utf-8
from api import thumbinfo
import os

def main():
    L = []
    # このスクリプトと同じ階層にある poll.list を読み込む
    poll_list = os.path.join(os.path.dirname(__file__), 'poll.list')
    f = open(poll_list, 'rb')
    for line in f:
        if line.find('#') == -1:
            video_id = line.strip()
        else:
            video_id = line[:line.find('#')].strip()
        if len(video_id) > 0:
            L.append(video_id)
    f.close()
    
    for vid in L:
        thumbinfo.run(vid)

if __name__ == '__main__':
    main()

poll.list

  • poll_thumbinfo.py と同じディレクトリに置く必要あり。
  • コメントが使えます。# 以降は無視されます。
nm7375388 # シング・ダンス・メロディ
sm3381792 # Dolls
sm3381726 # Ever
sm3381632 # Falling Rainbow
sm3375792 # Falling Rainbow/Ever/Dolls
sm2227394 # Aurora
sm2061292 # Higher than Clouds
sm1914307 # Linkage


実行スクリプトのパスを得る方法については、以下を参考にしました。