MENU

溶けかけてるうさぎ HP GALLERY BLOG TOP RECENT ARTICLES POPULAR ARTICLES ABOUT THIS BLOG

CATEGORY

大学 (140) 仕事 (17) 航空宇宙 (104) 写真 (78) 旅行 (32) 飯・酒 (17) コンピュータ (119) その他 (44)

TAG

ARCHIVE

RECENT

【写真】撮影写真を Map 上に表示できるようにした 【カメラ】X100 シリーズが好きすぎる(主にリーフシャッタ) 【カメラ】X100V から X100VI に買い替えました 【自宅サーバー】Google Domains から Cloudflare にドメインを移管 【カメラ】FUJIFILM XF レンズのサイズ比較ができるようにしてみた

【Twitter Bot】TLの334ツイートに対して,ツイート時刻をミリ秒精度でReplyする

事象発生日:2017-08-05

記事公開日:-

アクセス数:8228

334ツイート競争において,自分や他人のツイートの正確な時間が知りたいことがある.

公式クライアントからでは分単位でしかわからないので,ミリ秒単位でリプを飛ばしてくれるBotを作成した.

 

トップ画像の出典はこちら

1.はじめに

この記事は,「」の「」の続きである.

Twitter APIなどの環境構築については,「」を参照のこと.

2.動作環境

Ubuntu Server 16.04.2 LTS

Python 2.7.12

3.Pythonスクリプト

TLより334を含むツイートを取得し,ツイート時刻を返すスクリプトは下のようになる.

ツイートIDから時刻を取得する方法は,を参考にした.(はおそらくRubyで実装していた.)

 

また,APIを叩いて返ってくるJSONは,どうやらユニコード文字列のようだ.(つまりPythonのstr関数は使えない.)

# coding: UTF-8
import sys
import os
from requests_oauthlib import OAuth1Session
import json
import time
import datetime
import locale

CONSUMER_KEY        = '*************************'
CONSUMER_SECRET     = '**************************************************'
ACCESS_TOKEN        = '**************************************************'
ACCESS_TOKEN_SECRET = '*********************************************'
LOG_FILE = '${path}/log_334.log'

def main(args):
    twitter = OAuth1Session(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)

    # TL取得
    params =  { "count"           : 200,       # ツイートを最新から何件取得するか(最大200件)
                "exclude_replies" : "true",    # リプライを含めないか
              }
    req = twitter.get("https://api.twitter.com/1.1/statuses/home_timeline.json", params = params)
    timeline = json.loads(req.text)

    if (str(req) != "<Response [200]>"):
        # 追記モードで出力
        f = open(LOG_FILE, "a")
        try:
            # 文字列を出力
            f.write(GetStringTime()+"\t"+str(req)+"\tat home_timeline.json\n")
              #=> test12345test
        finally:
            f.close()

    ps(req)
    ps("\n")
    ps("##############################\n")

    i = 0;
    for tlTweet in timeline:
        ps("["+str(i)+"]\n")
        i += 1;
        ps(tlTweet["id"])
        ps("\n")
        ps(tlTweet["user"]["screen_name"])
        ps("\n")
        # 基本的にユニコード文字列? 取得できるJsonって.
        ps(tlTweet["text"].encode('utf-8'))
        # pu(tlTweet["text"])
        ps("\n")
        if (tlTweet["text"].find(u'334') > -1):
            # リプ飛ばす
            st = TweetId2Time(int(tlTweet["id"]))
            params =   {"status"                : "@" + tlTweet["user"]["screen_name"] + u"\nついーと時刻は,\n" + st + u"\nです.\n[Bot]",
                        "in_reply_to_status_id" : tlTweet["id"],
                        }
            req = twitter.post("https://api.twitter.com/1.1/statuses/update.json", params = params)
            if (str(req) != "<Response [200]>"):
                # 追記モードで出力
                f = open(LOG_FILE, "a")
                try:
                    # 文字列を出力
                    f.write(GetStringTime()+"\t"+str(req)+"\tat update.json\n")
                finally:
                    f.close()
            ps(req)
            ps("\n==================================\n")
            ps("\n\n")


    ps("\n")
    ps("\n")


def ps(output):
    sys.stdout.write(str(output))
    sys.stdout.flush()


def pu(output):
    sys.stdout.write(output)
    sys.stdout.flush()


def TweetId2Time(id):
    epoch = ((id >> 22) + 1288834974657) / 1000.0
    d = datetime.datetime.fromtimestamp(epoch)
    stringTime = ""
    stringTime += str(d.year)
    stringTime += '-'
    stringTime += '{0:02d}'.format(d.month)
    stringTime += '-'
    stringTime += '{0:02d}'.format(d.day)
    stringTime += ' '
    stringTime += '{0:02d}'.format(d.hour)
    stringTime += ':'
    stringTime += '{0:02d}'.format(d.minute)
    stringTime += ':'
    stringTime += '{0:02d}'.format(d.second)
    stringTime += '.'
    stringTime += '{0:03d}'.format(d.microsecond / 1000)
    return stringTime


def GetStringTime():
    d = datetime.datetime.today()
    stringTime = str(d.year)
    stringTime += '.'
    stringTime += '{0:02d}'.format(d.month)
    stringTime += '.'
    stringTime += '{0:02d}'.format(d.day)
    stringTime += '-'
    stringTime += '{0:02d}'.format(d.hour)
    stringTime += '.'
    stringTime += '{0:02d}'.format(d.minute)
    stringTime += '.'
    stringTime += '{0:02d}'.format(d.second)
    stringTime += '.'
    stringTime += '{0:02d}'.format(d.microsecond / 10000)
    return stringTime


if __name__ == '__main__':
    main(sys.argv)
334timechecker.py

今回も例によって例の如くソースコード編集ユーザーと実行ユーザーが違ったので,適当にパーミッションを変更.

$ sudo chmod 767 334timechecker.py

4.cronに定期実行の登録

今回は3:35と3:40に実行するようにした.

重複してReplyを送ってしまいそうだが,Twitterでは短い時間内に同じ内容を投稿できず,APIを叩いたときに403が返ってくるので,ひとまずは問題ない.

まあ,暇な時にでもきちんと実装します.

# バックアップは重要
$ crontab -l > ~/crontab.backup

$ crontab -e

# 以下を追記
35,40 3 * * * python /home/share/script/twitter/334timechecker.py > /dev/null 2>&1

5.参考サイト

GitHub. requests/requests-oauthlib. Retrieved August 3, 2017, from https://github.com/requests/requests-oauthlib
Twitter Developer Documentation. POST statuses/update. Retrieved August 3, 2017, from https://dev.twitter.com/rest/reference/post/statuses/update
Twitter Developer Documentation. GET statuses/home_timeline. Retrieved August 3, 2017, from https://dev.twitter.com/rest/reference/get/statuses/home_timeline
ソフトウェアエンジニアのためのtips. Python > 時間の処理. Retrieved August 3, 2017, from http://sweng.web.fc2.com/ja/program/python/time.html
Qiita. ツイートIDからツイート時刻をミリ秒まで算出(ついでに時刻からツイートIDを作成). Retrieved August 3, 2017, from http://qiita.com/riocampos/items/e5544325211976f2cfc1

関連記事

コメントを投稿

名前

Email (※公開されることはありません)

コメント