【Python】TwitterAPIとtweepyを使用してツイート自動化を行う方法

よく記事にあがっているようなPythonによるTwitterの投稿でハマった箇所があったので、実装の振り返りをしつつ記事に残しておこうと思います。

# 実装
```python:add_tweet.py
from pprint import pprint
import tweepy

import config

api_key = config.TWEETER_API_KEY
api_secret_key = config.TWEETER_API_SECRET_KEY
access_token = config.TWEETER_ACCESS_TOKEN
access_secret_token = config.TWEETER_ACCESS_SECRET_TOKEN

def clinet_info():
  """認証情報を返却する関数

  Returns:
      _type_: Client
  """
  client = tweepy.Client(
                        consumer_key=api_key,
                        consumer_secret=api_secret_key,
                        access_token=access_token,
                        access_token_secret=access_secret_token
                        )
  return client

# ツイートするテキスト
message = 'Hello World'

def create_tweet(message):
  """ツイートを行う関数

  Args:
      message (_type_): str

  Returns:
      _type_: str
  """
  tweet = clinet_info().create_tweet(text=message)
  return tweet

pprint(create_tweet(message))
```
コード自体はよくあるものですが、これで実行すると、`HTTP403エラー`となります。

# エラーの原因
結論から言うと、APIの設定に問題がありました。
具体的には、アプリケーションのパーミッションが、現在設定されている`Read and write`でなく初期状態の`Read`になっていました。

![スクリーンショット 2022-06-12 10.16.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/879778/14ea8e3f-3f05-9ab2-3b6e-aa3814a323e7.png)

そのため、`GETリクエスト`の実行は行えても、`POSTリクエスト`では書き込み権限のエラーが出てしまいます。
だからこそ、初期状態の`Read`ではなく、`Read and write`ないし`Read and write Direct message`に設定を変更することでエラーを解消できます。

なお、一度、設定を変更すると`Access Token`ならびに`Access Secret Token`の再発行が必要となるので、その点だけ注意が必要です。

※ tweepyでなく、APIを叩く場合も同様

簡単な実装ですが、意外とハマりやすい箇所なので、`403`と怒られている方には参考になるのではないでしょうか。

# ツイートを自動化する
上記に加え、投稿の自動化を行い、定期的にツイートしたい場合は、コードを以下のように変更します。

```python:add_tweet.py
from pprint import pprint
import tweepy
import schedule
from time import sleep

import config

api_key = config.TWEETER_API_KEY
api_secret_key = config.TWEETER_API_SECRET_KEY
access_token = config.TWEETER_ACCESS_TOKEN
access_secret_token = config.TWEETER_ACCESS_SECRET_TOKEN

def clinet_info():
  """認証情報を返却する関数

  Returns:
      _type_: Client
  """
  client = tweepy.Client(
                        consumer_key=api_key,
                        consumer_secret=api_secret_key,
                        access_token=access_token,
                        access_token_secret=access_secret_token
                        )
  return client

# ツイートするテキスト
message = 'Hello World'

def create_tweet(message):
  """ツイートを行う関数

  Args:
      message (_type_): str

  Returns:
      _type_: str
  """
  tweet = clinet_info().create_tweet(text=message)
  return tweet

# スケジュールを定義(10秒ごとに投稿)
schedule.every(10).seconds.do(create_tweet, message=message)

# イベントを実行
while True:
  # 定義したスケジュールで処理を実行する
  schedule.run_pending()
  # 1秒ごとにスケジュール定義した関数を呼び出す
  sleep(1)
```

`scheduleモジュール`と`sleep関数`をインポートして、スケジュールを定義し、ループ処理をするという内容を追加します。

ただし、これをそのまま実行すると`ツイートの重複はできない`と以下のエラーが出ます。
```
tweepy.errors.Forbidden: 403 Forbidden
You are not allowed to create a Tweet with duplicate content.
```

そのため、上記のコードを少し変更します。
```python:add_tweet.py
import random, string

def random_message(n):
  """n個のランダムな文字列を生成する関数

  Args:
      n (_type_): int

  Returns:
      _type_: str
  """
  return ''.join(random.choices(string.ascii_letters + string.digits, k=n))

def create_tweet():
  """ツイートを行う関数

  Args:
      message (_type_): str

  Returns:
      _type_: str
  """
  # ツイートするメッセージ
  message = random_message(10)
  tweet = clinet_info().create_tweet(text=message)
  return tweet

# スケジュールを定義(10秒ごとに投稿)
schedule.every(10).seconds.do(create_tweet)

# イベントを実行
while True:
  # 定義したスケジュールで処理を実行する
  schedule.run_pending()
  # 1秒ごとにスケジュール定義した関数を呼び出す
  sleep(1)
```
`randomモジュール`と`stringモジュール`をインポートして、ランダムな文字列を生成する関数を定義します。

その関数をツイートを生成する関数内で呼び出し、`create_tweet()`に渡すことでランダムな文字列を投稿できます。

また、それに付随し、スケジュールを定義している箇所では、第二引数で渡していた`message`を削除するひつようがあります。

このようにすると、定期的(上記のコードでは10秒ごと)にツイートを行うことができ、ツイートの自動化ができます。

※ 投稿したい内容をリストで定義し、ループで回し自動化する方法もあるかと思いますので、各々の仕様に合わせて実装してみてください。
私の場合は、「単純に定期投稿できるか」というテスト実装なので、上記実装となっています。

# 参考文献
・[【Python×Twitter】自動ツイート(投稿)を定期実行する方法｜APIとtweepyを用いたbot開発支援](https://di-acc2.com/system/rpa/9748/)

・[tweepy + Twitter API V2でツイート](https://qiita.com/penguinprogrammer/items/b220be0c203eaaad015a)

・[sched --- イベントスケジューラ](https://docs.python.org/ja/3/library/sched.html)
 
・[【Python】Scheduleモジュールを用いたイベント定期実行｜指定時間動作のスケジュール関数作成例と使い方解説](https://di-acc2.com/programming/python/4574/)

・[処理を一時停止！Pythonでsleepを使う方法【初心者向け】](https://techacademy.jp/magazine/15822)

・[Pythonを使ってランダムな文字列を生成](https://qiita.com/Scstechr/items/c3b2eb291f7c5b81902a)