前回の続きです。
今回は、前回得られた放送通知サーバへの接続情報を使ってsocket接続して放送通知を受け取ってみます。
ニコ生の放送通知サーバから放送通知を受け取るには、接続したsocketから
post_message = u'<thread thread="{0}" version="20061206" res_from="-1"/>\0'
post_message = post_message.format(thread)
という感じでリクエスト用のメッセージを送ります。
放送通知サーバがこちらからのリクエストを受信すると
<thread resultcode="0" thread="XXXXX" last_res="XXXXX" ticket="XXXX" revision="1" server_time="XXXX"/>
というthreadデータが返されます。
resultcode=”0″ が正常受信を意味していて、以後は継続的に放送通知が送られてきます(受信データの詳細はコチラのサイトが詳しく説明されています)。
受信データは
<chat thread="XXXXX" no="XXXXX" date="XXXXX" date_usec="XXXXX" user_id="XXX" premium="X">放送ID,コミュニティID,ユーザID</chat>\0<chat thread="XXXXX" no="XXXXX" date="XXXXX" date_usec="XXXXX" user_id="XXX" premium="X">放送ID,コミュニティID,ユーザID</chat>\0<chat ...
という形式で要素の放送通知が複数送られてきます。
この受信データを1件毎に切り分けて、放送ID,コミュニティID,ユーザIDを抽出すれば放送通知の受信部分としては良さそうです。
ということで、ここまでをスクリプトにしてみます。
socket接続はpython標準のsocketモジュールを使えばカンタンに出来ました。
socketを使ってデータ送信する方法とデータ受信する方法はソケットプログラミング HOWTOをほぼそのまま使ってます。
# -*- coding: utf-8 -*-
'''addr, port, threadは前回取得済み'''
import socket
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.connect((address, int(port)))
# リクエスト用のメッセージ
post_message = u'<thread thread="{0}" version="20061206" res_from="-1"/>\0'
post_message = post_message.format(thread)
# メッセージ送信(無限ループ)
total_sent = 0
while total_sent < len(post_message):
sent = socket.send(post_message[total_sent:])
if sent == 0:
raise RuntimeError(u'socket connection broken')
total_sent += sent
# メッセージ受信
while True:
# 上限4KBで受信
recv_stream = socket.recv(4096)
if recv_stream == '':
# 受信データが無いとき
raise RuntimeError('Socket connection broken')
else:
# 1件ごとに切り出し
receive_data_list = recv_stream.split('\0')
for xml_string in receive_data_list:
if len(xml_string) != 0:
# 放送通知
xml = Xml.fromstring(xml_string)
if xml.tag == 'chat':
alert = xml.text
alert_element = alert.split(',')
output_string = 'live_id: lv{0}, community_id: {1}, user_id: {2}'
print output_string.format(*alert_element)
いちおう放送通知を受け取ることが出来ました。
ただ、ここでは放送通知を表示してるだけです。
ニコ生アラートを作るためには、この通知を受け取って通知対象と突き合わせる必要があります。
通知対象との突き合わせはalert_elementリストと比較すれば良いわけですが、さすがにゴチャゴチャしすぎですw
なので、次回はここまでのスクリプトを整理してクラス化したいと思います。

コメント