3

Twitter のストリーミング API からデータをキャプチャし、各メッセージの受信時に redis pubsub を使用してチャネル「つぶやき」に公開する、孤立した python スクリプトがあります。これがそのスクリプトです:

def main():
    username = "username"
    password = "password"
    track_list = ["apple", "microsoft", "google"]

    with tweetstream.FilterStream(username, password, track=track_list) as stream:
        for tweet in stream:
            text = tweet["text"]
            user = tweet["user"]["screen_name"]
            message = {"text": text, "user": user}
            db.publish("tweets", message)

if __name__ == '__main__':
    try:
        print "Started..."
        main()
    except KeyboardInterrupt:
        print '\nGoodbye!'

私のサーバー側の socket.io 実装は、django-socketio (gevent-socketio に基づく) https://github.com/stephenmcd/django-socketioを使用して行われます。これは、単純にいくつかのヘルパー デコレータと broadcast_channel メソッドを提供します。これは django で行われるため、このコードを views.py に単純に配置して、インポートできるようにしました。私のviews.pyコード:

def index(request):
    return render_to_response("twitter_app/index.html", {
    }, context_instance=RequestContext(request))

def _listen(socket):
    db = redis.Redis(host="localhost", port=6379, db=0)
    client = db.pubsub()
    client.subscribe("tweets")
    tweets = client.listen()

    while True:
        tweet = tweets.next()
        tweet_data = ast.literal_eval(tweet["data"])
        message = {"text": tweet_data["text"], "user": tweet_data["user"], "type": "tweet"}
        socket.broadcast_channel(message)

@on_subscribe(channel="livestream")
def subscribe(request, socket, context, channel):
    g = Greenlet.spawn(_listen, socket)

クライアント側の socket.io JavaScript は、単純にチャネル「livestream」に接続してサブスクライブし、受信したメッセージをそのチャネルにキャプチャします。

var socket = new io.Socket();
socket.connect();
socket.on('connect', function() {
    socket.subscribe("livestream");
});
socket.on('message', function(data) {
    console.log(data);
});

このコードの明らかな問題は、新しいユーザーまたはブラウザー ウィンドウがページに対して開かれるたびに、新しい _listen メソッドが生成され、ツイートがサブスクライブされてユーザーごとにブロードキャストされるため、クライアントでメッセージが重複して受信されることです。私の質問は、クライアントの数に関係なく一度だけ作成されるように _listen メソッドを配置する適切な場所はどこでしょうか? また、broadcast_channel メソッドはソケット インスタンスのメソッドであることに注意してください。

4

1 に答える 1

3

問題は、socket.send を使用する必要があるときに、socket.broadcast_channel を使用していたことです。

于 2011-10-07T04:36:41.050 に答える