LoginSignup

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 5 years have passed since last update.

python3系でニコニコ動画のコメントを取得してみた.

Last updated at Posted at 2017-08-27

はじめに

中学から浸かり初めて,高校生になってからプレミアム会員になり8年目になりました.スクリーンショット 2017-08-27 23.55.39.png
525*12*8=50400円お布施しています💰

コメントを取得してみます

以下のコード動かせばコメント取得できます✌️
実行環境はPython3.6
使用ライブラリはurllib,http,xml

取得する動画はこちらにします
けものフレンズ 1話「さばんなちほー」 :1484126967

公式動画であれば,whenとwaybackkeyが効いて以下のプログラムで過去ログ取得できるのですが,ユーザ動画の場合whenがうまくいかないです.. どのようにすれば過去ログ取得できるか知ってる人いれば教えていただければ幸いです

key.py
#ニコニコ動画のログインするメアド&パスワード
mail="" 
password=""
GetComment.py
import urllib
import re
import http.client
import xml.etree.ElementTree as ET #xml
import time #sleep

from key import *

#ログイン処理
post_dict ={'show_button_facebook':'1',
    'next_url':'',
    'mail':mail,
    'password':password
}

headers['Referer']='https://account.nicovideo.jp/'
headers['Content-type']='application/x-www-form-urlencoded';
conn = http.client.HTTPSConnection('account.nicovideo.jp')
conn.request('POST','/api/v1/login?show_button_twitter=1&site=niconico',urllib.parse.urlencode(post_dict),headers)
rs = conn.getresponse()
mc = re.compile('(user_session=(?!deleted)[^;]*);?').search(rs.getheader('Set-Cookie'))
user_session = mc.group(1)
headers['Cookie'] = user_session
rs.read()
rs.close()
conn.close()

#動画情報の取得
videoid='1484126967' #kemono_friends_ep1

conn = http.client.HTTPConnection('flapi.nicovideo.jp', 80)
conn.request('GET', '/api/getflv/%s' % videoid, '', headers)
rs = conn.getresponse()
body = rs.read()
rs.close()
conn.close()

qs = urllib.parse.parse_qs(body.decode('utf-8'))
thread_id = qs['thread_id'][0] #thread_id
user_id = qs['user_id'][0]
print(thread_id , user_id)
#print(body)
mc = re.compile(r'&ms=http%3A%2F%2F(.+?)\.nicovideo\.jp(%2F.+?)&').search(body.decode('utf-8'))

message_server = urllib.parse.unquote_plus(mc.group(1))
message_path = urllib.parse.unquote_plus(mc.group(2))

#公式動画以外の取得では使わない
if videoid.find("sm") == 0:
    thread_key = None
    force_184=None
    waybackkey=None
else:
    conn = http.client.HTTPConnection('flapi.nicovideo.jp', 80)
    conn.request('GET', '/api/getthreadkey?thread=%s' % videoid, '', headers)
    rs = conn.getresponse()
    body = rs.read()
    rs.close()
    conn.close()
    qs = urllib.parse.parse_qs(body.decode('utf-8'))
    thread_key = qs['threadkey'][0] #thread_id
    force_184 = qs['force_184'][0]
    print(thread_key , force_184)

    conn = http.client.HTTPConnection('flapi.nicovideo.jp', 80)
    conn.request('GET', '/api/getwaybackkey?thread=%s' % videoid, '', headers)
    rs = conn.getresponse()
    body = rs.read()
    rs.close()
    conn.close()
    qs = urllib.parse.parse_qs(body.decode('utf-8'))
    waybackkey = qs['waybackkey'][0] #thread_id
    print(waybackkey)


動画のコメント取得
res_from=-1000 #コメントを現在から遡って何件取得してくるか
when=""
headers['Content-type'] = 'text/xml'

maxloop=2 #何回遡ってログを保存するかの回数
for loopcount in range(maxloop):
    #postXml = '<thread thread="%s" version="%s" res_from="%s" user_id="%s" threadkey="%s" force_184="%s"/>' % (thread_id,20090904,res_from,user_id,thread_key,force_184)
    postXml = '<thread thread="%s" version="%s" res_from="%s" user_id="%s" threadkey="%s" force_184="%s" when="%s" waybackkey="%s" />' % (thread_id,20090904,res_from,user_id,thread_key,force_184,when,waybackkey)

    conn = http.client.HTTPConnection('%s.nicovideo.jp' % message_server, 80)
    conn.request('POST', message_path, postXml, headers)
    rs = conn.getresponse()
    body = rs.read()
    rs.close()
    conn.close()

    #file_name = "gochiusa/tea_{}.xml".format(loopcount)
    file_name = "{}_{}.xml".format(videoid,loopcount)
    f = open(file_name,'w')
    f.write(body.decode('utf-8'))
    f.close()

    root = ET.fromstring(body)
    for child in root:
        if child.text !=None:
            when = child.attrib['date']
            break
    time.sleep(5)

コメント使って遊んで見た

取得したコメントの取得したい時間帯の前後5秒間のコメントの取得プログラムを書いて遊んで見ました.
スクリーンショット 2017-08-27 20.04.54.png

[('m9', 17), ('m9', 11), ('You are bag', 2), ('がーいど!', 2), ('かばんちゃんで!', 2), ('荷物持ちちゃんで!', 1), ('\u3000\u3000\u3000m9', 1), ('BAG-chan', 1), ('即決', 1), ('決断のはやいタイプ', 1)]

スクリーンショット 2017-08-27 22.16.32.png

[('すっごーい!', 85), ('すっごーい', 6), ('おこ?', 4), ('おこなの?', 3), ('ねこ?', 2), ('し', 2), ('こ', 2), ('マモレナカッタ…', 1), ('ドスコーイ', 1), ('何でためたし', 1)]

スクリーンショット 2017-08-27 22.53.09.png

[('おまかわ', 86), ('ごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごち', 6), ('ごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさ', 5), ('お前らは何の為にこの第1羽を観てるんだ・・・?', 1), ('どっちも頑張れ', 1), ('31秒守れよ', 1), ('31秒ルール絶対守れよな?', 1), ('omakawa', 1), ('大量出血w', 1), ('コメ数では勝っている!', 1), ('あやねるのアレがなかったらあねびtr', 1), ('a', 1), ('s', 1), ('おまかわってなんだよ', 1), ('敗\u3000\u3000北', 1), ('ごちうさぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁ', 1), ('この弾幕いる?', 1), ('負けるな', 1), ('きたーーーーーーーーーーーーーー', 1), ('31秒ルールが死んだ!', 1), ('ファー', 1), ('ラー', 1), ('おまきれ', 1), ('ごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさごちうさ', 1), ('この人でなし!', 1), ('@8qh\u3000test', 1)]

スクリーンショット 2017-08-27 23.59.39.png

【Just Be Friends】-piano.ver-を歌ってみた ver.Gero : sm9329290

[('やあ', 62), ('\(´・ω・)Heil Hitler\(´・ω・)', 16), ('わぁ!?', 14), ('Yeah! Nothing could be better than this! GALE BOOMERANG!', 14), ('やぁ', 10), ('やあああああああああああ', 4), ('わあ!?', 4), ('やああああああああああああ', 4), ('わぁ', 2), ('やあああああああああああああああああああああああああああああああああ', 2), ('やぁ^^', 2), ('やあああああああああ', 2), ('顔文字かわええwww', 2), ('歌えるしみけん', 2), ('やああああああああああああああああああああああああああああああああああ', 2), ('どりゃあああああああああああああああ', 2), ('やるお!?', 2), ('やああああああああ', 2), ('めっちゃ耕されてるなぁw', 2), ('約束の地', 2), ('ああああああああああああああああああああああああああああああああああ', 2), ('ああああああああああああああああああああああああああああああああああああ', 2), ('あああああああああああああああああああああああああああああああああああ', 2), ('ああああああああああああああああああああああああ', 2), ('おゲロ', 2), ('?', 2), ('久しぶりに来たぞ', 2), ('掲示板のgm使用直せ', 2), ('ゲロすげえwww', 2), ('!?', 2), ('やあああああああああああああああ', 2), ('砂の惑星から', 2), ('やあああああああああああああ', 2), ('ここを植民地とす!', 2), ('純配信してくれー;;', 2), ('目を覚ませ、お前はしみけんだ', 2), ('ええなぁ!?', 2), ('誰だMADタグつけたやつww', 2), ('金城', 2), ('泣くわ', 2), ('やあ!', 2), ('こんにちわーーーーーーーーーーーーーーーー', 2), ('替え玉すべーよ', 2), ('宅ゲロ', 2), ('やあああああああ', 2), ('けんしいいいいいいいいいいいいいいいいいいいいいいいいいいいいいい', 2), ('どんもー!', 2), ('なう(2017/08/19 10:54:34)', 2), ('コイツはGeroじゃないぞ?', 2), ('お、いきのいいセピアが沢山居るねぇ^^', 2), ('!????', 2), ('タグw', 2)]

こんな感じになります. 画像のSS取ってくるプログラムは書けそうですがめんどくさいので,自分で撮って来ました. この辺りもおそらく書けそうですが..

下に使ったコード一応公開しますが,適当に書いてるので綺麗に書き直したりした方がいいかも(苦笑)

time2comment.py
def time2comment(T,read_fileNum=1,step_on=False,fileName=None):
    from collections import Counter

    comment = []
    for N in range(read_fileNum):
        if fileName == None:
            #fileName = "kemono/friends_{}.xml".format(N)
            fileName = "gochiusa/tea_{}.xml".format(N)
        root0 = ET.fromstring(open(fileName).read())
        numlist = [i for i in range(T-5,T+5)]
        for num in range(0,len(root0)):
            if root0[num].text==None:
                continue
            #print(root0[num].attrib['vpos'])
            vpos = int(int(root0[num].attrib['vpos'])/100)
            if vpos in numlist:
                if step_on == True:
                    print(S2M(vpos),vpos,root0[num].text)
                comment.append(root0[num].text)
    print(Counter(comment).most_common())
def S2M(sec):
    m = int(sec/60)
    s = sec - 60*m
    return "{}:{}".format(m,s)
S2M(267)
# '4:27'
def M2S(h,m,s):
    return h*3600+m*60+s
M2S(0,6,30)
# 390

取得したコメントでWordCloudしてみる.

ニコニコ動画のコメントってみなさんご存知の通り,形態素解析と相性最悪なんですよね.. ともかく,集めたコメントでWordCloudしてみます.

  • まず最新1000件のコメントで作って見たやつ

ダウンロード (1).png

  • わーい(17:38のシーン)
    ダウンロード (2).png

  • 最後に180万コメントで作って見たやつ
    wktkey_2017-8月-29.png

終わりに

以上,ニコニコ動画のコメントを取得してみました.
大域的に動画のコメント使って遊ぶ場合は国立情報学研究所 -ニコニコデータセットを使えばいいと思いますがピンポイントで欲しい動画のコメントだけ欲しい場合には...

参考リンク

classic-style Pythonでニコニコ動画のコメントを取得する方法

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up