はじめに
せっかくラズパイを買ったので何か作ってみようと思い開発に着手しました。
目標は30分に1回、過去30分のツイートを読み上げてくれる感じです。
私自身PythonもLinuxもほぼ初心者ですので間違いがあると思いますので、その際はご指摘いただければ幸いです。
環境
-RaspberryPi 3 (Raspbian)
-Python3.5.3 (アップデートしてなかった…)
-AquesTalkPi
-Tweepy
事前準備
1.Twitterアプリの登録とTweepyのインストール
Qiita登録前にはてなブログに書いたのでそちらをご覧ください。
2.AquesTalkPiのインストール
OpenJTalkというソフトもありますが、AquesTalkPiを使ってみました。
個人の非営利利用に限り無償とのことなので。
インストールや使用方法は下記リンクのまとめを参考にさせていただきました。
実装
上から順にコードの内容と意図を説明していきます。
例外処理してないけど…
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tweepy
import subprocess
from datetime import datetime, timedelta, timezone
import pytz
今回使うパッケージをimportします。
#時刻設定
JST = timezone(timedelta(hours=+9),"JST")
now = datetime.now(JST)
old = now- timedelta(minutes=30)
タイムラインの取得は件数指定しかできないようなので
スクリプトの起動時刻と比較して範囲外のツイートは読み上げないようにしたい
と思って時間を取得しています。わざわざ日本標準時にしている理由は後述。
#key
CONSUMER_KEY = 'xxxxxxxxx'
CONSUMER_SECRET = 'xxxxxxxxx'
ACCESS_TOKEN = 'xxxxxxxxx'
ACCESS_SECRET = 'xxxxxxxxx'
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)
api = tweepy.API(auth)
#TL取得(最新30件)
i = api.home_timeline(id="ユーザID", count=30)
Twitterアプリ登録で取得したキーを使ってTwitterAPIを呼び出します。
このコードでは自分のタイムライン上の30件を取得しています。
200件までいけるらしいけどフォローしている人が少ないので十分かと。
#読み上げ機能
#抽出結果を逆に読み込み
for result in i[::-1]:
#ツイート時刻をJSTに変換
created = pytz.utc.localize(result.created_at)
created = created.astimezone(JST)
#指定した時間より前のツイートは対象外
if created >= old:
#ツイートに"が含まれると動かないので置き換え
text = result.text.replace("\"","")
cmd = "/home/pi/aquestalkpi/AquesTalkPi -s 130 \""+ text +"\" |aplay"
subprocess.call(cmd, shell=True)
else:
continue
print("done!")
取得したツイートのリストは新しい順になっているので逆からループさせています。
その後、created_atを日本標準時に変換し、スクリプト起動の30分前の時間と比較しています。
そして30分以内のツイートであればAquesTalkPiに渡し、それ以外なら次のツイートへ。
ちなみに -s 130 は速度変更のオプションでデフォルトは100です。
定期実行の設定
cronを設定して今回作成したスクリプトを定期実行するようにします。
# m h dom mon dow command
0,30 9-23 * * 6,7 python3 call_aquestalkpi.py
これで毎週土日の9:00〜23:30まで30分毎に読み上げてくれます。
感想
Pythonのタイムゾーンの概念を知らなかったため時間比較が一番苦戦しました…
時間比較自体は下記の記事を参考にさせていただいたのですが全く上手くいかない。
というわけで色々調べたところ公式ドキュメント内に下記の記述を発見。
"naive" と "aware" の2種類の日付と時刻オブジェクトがあります。
時間型には2種類のオブジェクトがあり、タイムゾーンを明示しないとnaiveになり、
naiveとawareの間では時刻の比較ができないとのことです。
そして今回取得してきたツイートの書き込み時刻はnaiveです。
そのためタイムゾーンの補正が必要だったわけです。勉強になりました。
というか普通に急にゆっくりが話すのびっくりするので早々に読み上げさせなくなる予感。。。
参考URL
下記の記事を参考にさせていただきました、ありがとうございます!
AquesTalk Pi の使い方まとめ
Pythonの UTC ⇔ JST、文字列(UTC) ⇒ JST の変換とかのメモ
[cron]定期的に処理を行う
Python datetime 日付の計算、文字列から変換【決定版】
8.1. datetime — 基本的な日付型および時間型