$a(){ a|a& };a

ふくし…の大学?に通ってるんですけど!

ごちうさ速報Botを作った

この記事は KMC Advent Calendar 2016 及び ごちうさ Advent Calendar 2016 の15日目の記事です。

KMC Advent Calendar の前回の記事は uiureoさんの記事…はまだないので、その前の記事は walkureさんのゼネコンを九ヶ月で辞めた話 - (。・ω・。)ノ・☆':*;':* でした。 ごちうさ Advent Calendar の前回の記事は kivantiumさんの きんモザ・ごちうさ聖地巡礼記 - kivantium活動日記 でした。

はじめに 〜デキるエリートの場合〜

みなさんは、最新の社会情勢や時事が知りたい時、どうしていますか? テレビをつけてニュースを見ますか? それとも Yahoo!トップのニュースを見ますか? デキるエリートはそんな俗世的で時間のかかることはしません。

デキるエリートはまず「1」と検索窓に打ち込みます。 f:id:CHY72:20161214164244p:plain 素晴らしい。 誰でもこの方法で ご注文はうさぎですか? 第1羽「ひと目で、尋常でないもふもふだと見… を見つけられます。 デキるエリートはこの ニコ動のごちうさ1期一話 を見て最新の社会情勢をたったの30秒で把握します。

上の動画は 実際の2016/12/14/23時のごちうさ1羽の開始30秒です。 たかがアニメ動画と侮ることなかれ、この30秒で例えば

などのように様々なジャンルの社会情勢が分かってしまいます。

ごちうさ速報

このニュース速報は「ごちうさ難民」と呼ばれる人たちが投稿しています。 ご注文はうさぎですか? 第1羽「ひと目で、尋常でないもふもふだと見抜いたよ」とは にも詳しい説明がありますが、 ごちうさの「心をぴょんぴょんさせる性質」に救われ、この動画を毎日見続け、ごちうさという安住の地を手に入れた人々のことです。 やがて彼らはこの動画のコメントで情勢を報告しあうようになり、この動画を見るだけで昨今の情勢が分かるレベルまでに成長することとなったのです。

12月4日19時、我らがチノちゃんの誕生日には、一面シアン一色になりました。

ごちうさ速報は誰もが自由に書き込めるという性質上中立性があるといえます。 例えばテレビニュースの場合、スポンサーなどの影響で中立な放送をすることは難しいでしょう。 恣意的なニュースを流すことも可能ですが、日本中の人々が視聴するお茶の間のテレビ等とは異なり、 ごちうさ難民を扇動するニュースを流すメリットは皆無であるので、そのようなニュースは紛れ込みにくいといえます。 (逆に言うと、「ごちうさ3期決定!」「ゆゆ式二期決定!」などのように扇動するメリットのあるニュースはたまに紛れ込みます。)

Bot

このように有用なごちうさ速報をもっと簡単にシュッと確認できるようにしたいものです。 そこで、ごちうさ1羽を定期的に観察し呟くtwitterBotを作成することにしました。 以下、 KMCアドベントカレンダーらしく、そのPython3での実装について技術的なことを記述します。

ログイン

def login(mail_tel, password):
    s = requests.session()
    s.post('https://account.nicovideo.jp/api/v1/login?site=niconico', params={
        'mail_tel': mail_tel,
        'password': password,
    })
    return s

requestsモジュールを用いると簡単にログインできます。 引数のメールアドレスやパスワードはご自分のものをどうぞ。

コメント取得

ニコニコ動画APIについては、 ニコニコ動画APIとは 等に 掲載されていますが、詳しい使い方についてのドキュメントはあまり整備されておりません。 更にネットで検索して得られる情報は古いものや誤っているものも多く、 結局のところ実際の通信内容を見てコードに落とし込むのが一番手っ取り早いです。

def get_comments(thread_id, s, ok_time=3100, version="20090904"):
    movie_info = s.post("http://flapi.nicovideo.jp/api/getflv/{thread_id}".format(thread_id=thread_id))
    qs = parse_qs(movie_info.text)
    ms, user_id, userkey = qs["ms"][0], qs["user_id"][0], qs["userkey"][0]
    optional_thread_id = qs["optional_thread_id"][0]
    thread_info = s.get("http://flapi.nicovideo.jp/api/getthreadkey?language_id=0&thread={thread_id}".format(thread_id=thread_id))
    found = re.findall(r'threadkey=(.+)&force_184=(.+)', thread_info.text)
    threadkey, force_184 = found[0]
    xml = """<packet> <thread thread="{thread}" version="{version}" user_id="{user_id}" threadkey="{threadkey}" force_184="{force_184}" scocomments="1" with_global="1" /> <thread_leaves thread="{thread}" user_id="{user_id}" threadkey="{threadkey}" force_184="{force_184}" scocomments="1" >0-24:100,1000</thread_leaves> </packet>""".format( version=version, thread=thread_id, opt_thread=optional_thread_id,user_id=user_id, threadkey=threadkey, force_184=force_184)
    comments = requests.post("http://nmsg.nicovideo.jp/api/", data=xml)
    founds = re.findall(r'<chat (.+?)>(.+?)</chat>',comments.content.decode("utf-8"))
    comments = []
    for info, found in founds:
        found = found.replace("\u3000", " ") #全角空白
        vpos = int(re.findall(r'vpos="(\d+)"', info)[0])
        date = int(re.findall(r'date="(\d+)"', info)[0])
        mail = re.findall(r'mail="(.+?)"', info)
        mail = mail[0] if mail else ""
        if len(found) > 30 or len(found) < 4 or vpos > ok_time:
            continue
        comments.append([found, vpos, date, mail])
    comments.sort(key=lambda x: x[1])
    return comments

引数の thread_id には ごちうさ1羽は、http://www.nicovideo.jp/watch/1397552685 ですので、 1397552685 が入ります。 s には先程のログインで作成したrequestsのsessionが入ります。 ok_timeは、ごちうさ速報は開始31秒*1なので、31*100の3100を入れます。

getflvAPI,getthreadkeyAPIにて動画情報、視聴ユーザー情報、コメントサーバー情報を取得し、 判明したコメントサーバーに生成したxmlを投げることで最近のコメント一覧のxmlを取得しています。 コメントには以下の3つの属性があり、

属性名 意味
vpos コメントが動画上で表示される時刻
date コメントが投稿された時間
mail ue shita red cyan big など、文字への修飾

vposでソートし、処理しやすい配列の形で返却します。

動画生成

コメントを取得できたので、後はその情報を元にして動画を生成するだけです。 動画の生成には moviepy を用いると楽ちんです。 結論としては analyze_mp4.py · GitHub みたいな関数を作れば ニコニコ動画を再現できます。 make_textclip関数でコメントをmailとvposを元にして動画に合成します。 コメントのフォントに際しては、フォント変化と明朝化DR10行固定:meg_nakagamiのブロマガ - ブロマガ に詳細が載っています。 再生環境によってフォントは変わるようですが、今回は実行パスと同階層に置いた hiragino.ttc を合成することにしています。 テスト用の非公開動画を投稿し、コメントを投げて感覚を掴み、それを元にしたノリでコメントを流しています。

動画投稿

結論としては twitter72.py · GitHub のtweet関数のような感じで投稿できます。 tweepy 等を使ってもよかったのですが、mp4の投稿はうまくいかなかったので、twitter公式ドキュメント などを参考にして実装しました。

実際のコード

以上をまとめると、

twitter72.py · GitHub

gochiusa_sokuho.py · GitHub

が、最終的にコードとして完成されます。 ログイン情報やトークンをまとめたファイル gochiusa_token を作り、 あとは環境さえ揃っていれば $python3 gochiusa_sokuho.py mp4 で動画生成からツイッター投稿までできるようになります。

運用

以上のコードにより、目的のBotが完成しました。

このBotは一日に2回、30秒の動画を投稿し、 一時間に一度コメントをチェックして更新があればコメントを呟いています。 全部呟くと流石にキリがないので、赤色で大文字のもののみ呟くようにしています。

まとめ

こうして我々は社会情勢を簡単に知ることができるようになりました。 更に毎日投稿しているので、先程のチノちゃん生誕祭のように気になった日のアーカイブをいつでも確認できるようになりました。 毎日欠かさず情報を提供してくれるごちうさ難民のみなさまには感謝の意しかありません。 ごちうさ1羽 は、現在7777777回再生を突破*2し、その人気はまだまだ健在です。 これからも心をぴょんぴょんさせていきましょう。

明日のKMCアドベントカレンダーは pastak さんによる「多分ポエム」、 明日のごちうさアドベントカレンダーは hideo54 さんによる 「青山ブルーマウンテンさんから学ぶ対原稿術」です。

それでは また来るよ、マスター。