TweepyとcronでTwitterボットを作ってみた話

# この記事に書いてあること
PythonでTwitterボット作ってみたのでそこでやったことをまとめました。
TwitterAPIのアカウント登録申請してLinuxサーバにPythonとTweepyをインストールしてPythonでプログラムを書いてcronで時間になったらプログラム起動してつぶやくという流れです。

# TwitterAPIのアカウント登録申請
Pythonでやってみたかったので、いろいろ調べたらTweepyというTwitterのAPIをラップしたサービスを発見。使いやすそうだと思ったのでこれを使ってみる。
しかしいずれにしてもTwitterAPIのアカウントが必要です。私は[この記事](https://qiita.com/kngsym2018/items/2524d21455aac111cdee)を参考にアカウントを申請しました。
これで取得する以下4項目が後程重要になります。
- CONSUMER_KEY
- CONSUMER_SECRET
- ACCESS_TOKEN
- ACCESS_TOKEN_SECRET

### 参考
- [Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ　※2019年8月時点の情報](https://qiita.com/kngsym2018/items/2524d21455aac111cdee)
- [twitter developerサイト](https://developer.twitter.com/en)

# LinuxにPythonインストール
私はサクラインターネットでLinuxサーバ(CentOS)をレンタルしているので、それにPythonをインストールします。[この記事](https://www.sejuku.net/blog/33294)を参考にしました。
以下のコマンドで、IUS Community Projectのリポジトリを持ってきます。

```
sudo yum install -y https://centos7.iuscommunity.org/ius-release.rpm
```

次に、以下のコマンドでPython3をインストールします。

```
sudo yum install  -y python36u-devel python36u-pip
```

Pythonがインストールされたか確認します。

```
python --version
```

インストールしたバージョンが表示されればOKです。

```
Python 3.6.2
```


### 参考
- [Pythonのインストール方法をOS別に解説（Windows・Mac・Linux）](https://www.sejuku.net/blog/33294)


# Tweepyを使用してPythonプログラム作成
プログラムを作成するために、まずはTweepyをインストールします。pipが入っていれば、`pip install tweepy`でインストールできます。

### 文字列のみでつぶやく
Tweepyをインストールした後は以下のようなプログラムを書きました。指定したアカウントのフォロワー数を取得してつぶやくというものです。

```python:TwitterBot
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
sys.path.append('/usr/local/lib/python3.6/site-packages')

import tweepy

CONSUMER_KEY = "[twitterAPIのアカウント作成で取得した値]" 
CONSUMER_SECRET = "[twitterAPIのアカウント作成で取得した値]"
ACCESS_TOKEN = "[twitterAPIのアカウント作成で取得した値]"
ACCESS_TOKEN_SECRET = "[twitterAPIのアカウント作成で取得した値]"

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth ,wait_on_rate_limit = True)

# フォロワー数の取得
user = api.get_user(screen_name="[twitterアカウント名（「@」は除く）]")
count = user.followers_count

# つぶやきたい内容の文字列を生成
# （この内容だと指定したアカウントのフォロワー数をつぶやきます）
message= str(count)

# つぶやく
api.update_status(message)

```

### 画像付きでつぶやく（単一画像）
文字だけではなく、画像付きでつぶやきたい場合はこんな感じです。当プログラムと同一ディレクトリに「xxx.png」という画像ファイルが置いてある前提でのプログラムです。
最後に呼び出す関数が変わっているぐらいで、他は基本的に先ほどと同じです。

```python:TwitterBotSinglePicture
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
sys.path.append('/usr/local/lib/python3.6/site-packages')

import tweepy

CONSUMER_KEY = "[twitterAPIのアカウント作成で取得した値]" 
CONSUMER_SECRET = "[twitterAPIのアカウント作成で取得した値]"
ACCESS_TOKEN = "[twitterAPIのアカウント作成で取得した値]"
ACCESS_TOKEN_SECRET = "[twitterAPIのアカウント作成で取得した値]"

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth ,wait_on_rate_limit = True)

# つぶやきたい内容の文字列を生成
message = str("私はbot\n")

# 文字列と単一画像の投稿
api.update_with_media(filename='xxx.png', status=message)

```

### 画像付きでつぶやく（複数画像）
画像を複数枚添付してつぶやきたい場合はこんな感じです。当プログラムと同一ディレクトリに「xxx1.png」、「xxx2.png」という画像ファイルが置いてある前提でのプログラムです。

```python:TwitterBotSinglePicture
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
sys.path.append('/usr/local/lib/python3.6/site-packages')

import tweepy

CONSUMER_KEY = "[twitterAPIのアカウント作成で取得した値]" 
CONSUMER_SECRET = "[twitterAPIのアカウント作成で取得した値]"
ACCESS_TOKEN = "[twitterAPIのアカウント作成で取得した値]"
ACCESS_TOKEN_SECRET = "[twitterAPIのアカウント作成で取得した値]"

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth ,wait_on_rate_limit = True)

# つぶやきたい内容の文字列を生成
message = str("私はbot\n")

# 複数画像を添付
file_names=["xxx1.png", "xxx2.png"]
media_ids = []
for filename in file_names:
    res = api.media_upload(filename)
    media_ids.append(res.media_id)

# 文字列と複数画像の投稿
api.update_status(status=message, media_ids=media_ids)

```

※単一画像のときも最後に呼び出す関数は`api.update_with_media`ではなく`api.update_status`で行けそうな気がしますが未検証です。

### 参考
- [Tweepyで雑にTwitter botを作ってみた](https://qiita.com/tsc343/items/e51f412480ea8bf5619a)
- [Python Tweepyを利用して、Twitter APIを使ったデータ収集方法を初心者向けに徹底解説してみた](https://dividable.net/python/python-twitter-api-get-followers-count/)
- [Python初心者が　ModuleNotFoundError: No module named 'tweepy' で挫けそうになった話](https://qiita.com/1_am_kou/items/8e66f7ad9e7dc49a14cc)
- [Tweepyドキュメント](https://kurozumi.github.io/tweepy/)
- [API reference index](https://developer.twitter.com/en/docs/api-reference-index)
- [Pythonで『tweepy』を使いこなす方法【テキスト・改行・複数画像添付】](https://karupoimou.hatenablog.com/entry/2019/05/17/080251)
- [Tweepy で Twitter に画像付きのツイートをする](https://qiita.com/ekzemplaro/items/f0c768215d7d1a7b90ac)


# cron設定
主に[この記事](https://qiita.com/katsukii/items/d5f90a6e4592d1414f99)を参考にcronの設定をしていきました。
最初は、毎日8時に稼働するように設定しました。`crontab -e`で以下のように編集します。

```
0 8 * * * [実行コマンド(python /XXX/XXX.py)]
```

暫くすると8時と19時に稼働させたくなったので、今度は`crontab -e`で以下のように編集しました。

```
0 8,19 * * * [実行コマンド(python /XXX/XXX.py)]
```

最終的には1時間おきに稼働させたくなったので、今度は以下のように編集しました。

```
0 */1 * * * [実行コマンド(python /XXX/XXX.py)]
```

お役御免になったので、`crontab -ir`コマンドでcronの設定を削除しました。
※`crontab -r`で削除することもできますが、オプションを`-ir`とすることで削除前に本当に削除していいか認してくれます。

各コマンド実行後は、毎回`crontab -l`で設定内容を確認するようにしていました。



### 参考
- [クーロン(cron)をさわってみるお](https://qiita.com/katsukii/items/d5f90a6e4592d1414f99)
- [crontabコマンドについてまとめました 【Linuxコマンド集】](https://eng-entrance.com/linux-command-crontab)
- [cronの設定方法](https://qiita.com/hikouki/items/e744b3a4d356d2af12cf)
- ["crontab" -r でいきなり削除しないようにする @LCD -Linux Command Dictionary- 【山澤】](https://www.rep1.co.jp/staff/200vcxg/217rav/crontab_-r_lcd_-linux_command.htm)
- [/etc/crontabと/etc/cron.d設定ファイルの書き方](https://www.server-memo.net/tips/etc-crontab.html)
- [cron の設定ガイド](https://www.express.nec.co.jp/linux/distributions/knowledge/system/crond.html)
- [crontab（cron）設定確認方法](https://www.server-memo.net/tips/crontabfile.html)

# 結果
こんなBOTができましたとさ。

### 文字列のみのつぶやき

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【テストです】<a href="https://twitter.com/sagamax__?ref_src=twsrc%5Etfw">@sagamax__</a> のBOTだよ。<br>今2020年06月06日 21時52分。<br>今日は土曜日。<br>R杯はもうやった？明日までにはやらないとね！<a href="https://twitter.com/hashtag/%E3%83%AD%E3%83%9E%E3%82%B5%E3%82%ACRS?src=hash&amp;ref_src=twsrc%5Etfw">#ロマサガRS</a></p>&mdash; sagamax_bot (@sagamax_bot) <a href="https://twitter.com/sagamax_bot/status/1269250828986023937?ref_src=twsrc%5Etfw">June 6, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

### 画像を1枚だけ添付してつぶやいた結果
こんな感じ

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/sagamax__?ref_src=twsrc%5Etfw">@sagamax__</a> のbotだよ。<br>今2020年06月06日 23時46分。<br>今日は土曜日。<br>R杯とツヴァイクはもうやった？明日までにはやらないとね！<br>R杯で秘伝書、ツヴァイクでゴルピをもらおうね！<br>鉱石交換所のスタ剤も明日までにもらおうね！<a href="https://twitter.com/hashtag/%E3%83%AD%E3%83%9E%E3%82%B5%E3%82%ACRS?src=hash&amp;ref_src=twsrc%5Etfw">#ロマサガRS</a> <a href="https://t.co/7jpcZNxfTA">pic.twitter.com/7jpcZNxfTA</a></p>&mdash; sagamax_bot (@sagamax_bot) <a href="https://twitter.com/sagamax_bot/status/1269279485301424128?ref_src=twsrc%5Etfw">June 6, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

### 画像を複数枚添付してつぶやいた結果
こんな感じ

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">私は<a href="https://twitter.com/sagamax__?ref_src=twsrc%5Etfw">@sagamax__</a> のbotだよ<br>今2020年06月07日 12時00分<br>今日は日曜日。<br>R杯はもうやった？今日やらないと秘伝書がもったいないよ！<br>あとツヴァイクも！ゴルピゴルピ！<br>鉱石交換所でスタ剤ももらおうね！<a href="https://twitter.com/hashtag/%E3%83%AD%E3%83%9E%E3%82%B5%E3%82%ACRS?src=hash&amp;ref_src=twsrc%5Etfw">#ロマサガRS</a> <a href="https://t.co/Fp6XhjFZsm">pic.twitter.com/Fp6XhjFZsm</a></p>&mdash; sagamax_bot (@sagamax_bot) <a href="https://twitter.com/sagamax_bot/status/1269464107477917696?ref_src=twsrc%5Etfw">June 7, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>