こんにちは、RPA事業部です。
久しぶりの投稿になりますが、また定期的に更新できるようにがんばりたいと思います。

今回は、Twitter API v2とPythonを使用して、自動ツイートbotを作成しましたので、その内容を実際のコードなどを交えて紹介していきます。

以前からTwitter APIを使用して何かしてみたいと思っていましたが、まずはツイートを自動化するところから始めてみることにしました。

また、いつも同じ内容だとつまらないので、コチラのサイトから本日日付にまつわる記念日をランダムに1つ取得して、それをツイート内容にする仕様にしています。

では、実際にみていきましょう。

Twitter APIを利用するために必要なこと

必要なことは以下になるかと思います。
・Twitter APIの申請
・APIキー・トークンの取得

本コラムはあくまで自作ツール紹介であるため、上記の申請・取得手順は省略しますが、以下のサイトを参考にしました。
参考サイト:Twitter APIの申請方法を解説【2022年版】

内容紹介

自動ツイートbotの内容は以下のようになります。

botがすること

今日日付の記念日を取得しツイート。

使用方法

作成したプログラムファイルをバッチファイルで実行。

プログラムを定期実行するために、タスクスケジューラで決まった時間にバッチファイルを起動するように設定。
→指定日時にツイートが自動投稿される。

処理の流れ

  1. 記念日の情報を取得
  2. API接続
  3. APIを利用して、ツイートをする
  4. 動作結果をコマンドプロンプト上に出力する

動作結果

結果はこんな感じになります。

コード内容

コード内容を大まかに紹介していきます。

動作環境

Python:3.9.0

ファイル構成

ファイル構成は以下の通りになります。

.
┗exe_pyfile.bat
┗config.py
┗main.py

内容紹介

下記のconfig.pyには、取得したAPIキー・トークンを記載しています。

'''
api認証に必要な下記要素をそれぞれ記述してください
    ・api key
    ・api key secret
    ・access token
    ・access token secret
'''

CLIENT = {
    'API_KEY':'...',
    'API_KEY_SECRET':'...',
    'ACCESS_TOKEN':'...',
    'ACCESS_TOKEN_SECRET':'...',
}

下記がプログラム実行用のバッチファイルです。このバッチファイルを叩けばコマンドプロンプトが起動され、動作結果が出力されます。

また、このバッチファイルが定期実行されるようにタスクスケジューラを設定していきます。設定方法ついて、下記サイトを参考にしました。

参考サイト:【Windows 10対応】タスクスケジューラで定期的な作業を自動化する

@echo off

python .\main.py
pause

下記がAPI接続やツイートなどを行う、メインのコードになります。

import random
import datetime
import sys
import requests
from time import sleep
from requests_oauthlib import OAuth1Session
from config import CLIENT
from bs4 import BeautifulSoup

#リクエストエラーが発生した場合のリトライ回数
RETRY_TIME = 5
#記念日取得用URL
ANNIV_URL = r'https://zatsuneta.com/category/anniversary.html'

def main():
    
    anniv_lists = fetch_anniv()

    #リストが空の場合は取得失敗として処理を中断
    if len(anniv_lists) == 0:        
        print(f"{'#'*10}\nFail to fetch anniversary\nCancel all processing\nPlease try again\n{'#'*10}")
        sys.exit()
    else:        
        rand_num = random.randrange(0,(len(anniv_lists)-1))
        anniv_name = anniv_lists[rand_num][0]
        anniv_link = anniv_lists[rand_num][1]

        #選択した記念日出力
        print(f"{'#'*10}\nselected_anniversary --> {anniv_name}\nlink --> {anniv_link}\n{'#'*10}")        
        
        results = post_tweet(anniv_name,anniv_link)

        #結果出力
        if results['code'] != 201:
            print(f"Tweet is failed\nstatus_code --> {results['code']}\ndetail --> {results['response']['detail']}\n{'#'*10}")
        else:
            print(f"Tweet is Succeed\n{'-'*3}tweet_text{'-'*3}\n{results['response']['data']['text']}\n{'#'*10}")      
    
#記念日一覧の取得関数(取得に失敗した場合、空のリストを返す)
def fetch_anniv():

    res = None

    try:
        res = requests.get(ANNIV_URL)
    #エラーが発生した場合、リクエストリトライ実行(回数はRETRY_TIME定数で設定)
    except Exception as err:

        print(f"{'#'*10}\nREQUETS_ERROR --> {err}\nstart_retry_requests\n{'#'*10}")
        sleep(1.5)

        cnt_loop = 1
        while cnt_loop <= RETRY_TIME:
            try:
                print(f'RETRY_COUNTER --> {cnt_loop}')     
                res = requests.get(ANNIV_URL)
            except Exception as err:
                print(f'REQUETS_ERROR --> {err}')
                sleep(1.5)
                pass
            else:
                print(f"SUCCESS_TO_CONNECTING_NETWORK\n{'#'*10}")
                break            
            
            cnt_loop += 1
        
    if res == None:
        return_val = []
    else:
        
        sp = BeautifulSoup(res.text,'html.parser')
        elms = sp.select('#contents > div.article:nth-child(2) > p > ul > li:nth-child(n) > a')
        
        anniv_names = [elm.text for elm in elms]
        anniv_links = [elm.get('href') for elm in elms]
        return_val = list(zip(anniv_names,anniv_links))

    return return_val

#api接続の関数
def define_client():
    AK = CLIENT['API_KEY']
    AKS = CLIENT['API_KEY_SECRET']
    AT = CLIENT['ACCESS_TOKEN']
    ATS = CLIENT['ACCESS_TOKEN_SECRET']

    return OAuth1Session(AK,AKS,AT,ATS)

#ツイート処理の関数
def post_tweet(param_text:str,param_url:str):

    #テキスト編集
    today = datetime.date.today()
    edited_text = f'本日は{today.year}年{today.month}月{today.day}日、「{param_text}」です。\n\n今日も頑張っていきましょー!!\n\n紹介した記念日については「{param_url}」を参考にしています。気になったらぜひご覧ください。'
    
    api = define_client()
    resource_url = r'https://api.twitter.com/2/tweets' #エンドポイントURL

    params = {
        "text":edited_text
    }

    res = api.post(resource_url,json=params)
    dict_results = {'code':res.status_code,
                    'response':res.json()}

    return dict_results

if __name__ =='__main__':
    main()

コードの大まかな説明

メイン部分に関して、大まかに説明していきます。

1.指定したURLから本日日付の記念日一覧を取得

下記のライブラリを使用して、本日日付の記念日一覧をまとめてcssセレクタで指定し抽出しています。

  • Requests
  • Beautiful Soup

ここで、うまく記念日を取得できない場合は、空のリストを作成・メイン関数に引き渡し、処理を中断するようにしています。

取得できた時は、記念日のリストを作成し、数に応じたランダムな整数を生成し、ツイート内容となる記念日を選択します。

2.API接続

OAuth認証を簡単に行うためのライブラリ「requests-oauthlib」を使用して、APIに接続します。

また、「OAuthとは何?」という方は以下のサイトが参考になるかと思います。

<参考サイト>
一番分かりやすい OAuth の説明
【連載】世界一わかりみの深いOAuth入門

3.ツイート・結果出力

選択された記念日の情報と本日日付をもとにツイート内容を生成します。

次に、上記で取得した「api」オブジェクトを呼び出し、エンドポイントのURLとツイート内容を指定してリクエストを送信します。

最後に、レスポンスのステータスコードをもとにツイートが成功したか、失敗したかを判定し、結果をコマンドプロンプトへ出力して一通りの処理が終了です。

※API制限について

APIを使うと、大量にツイートを投稿するなどが簡単にできてしまうため、一定時間ツイート回数や内容取得数などが制限されています。

なお、ツイート投稿に関しては15分当たり最大で200まで、加えて3時間あたりではリツイートも含めて300件となっています。

大量にツイートするbotを作成する場合は、こちらも考慮する必要がありそうです。
API制限の詳細は公式ドキュメントを参照してみて下さい。

実行結果

実行結果は下記画像のようになりました。

成功

コマンドプロンプト出力結果

Twitter上

失敗

下記のエラーはAPI認証エラーです…

おわりに

いかがだったでしょうか。

今回はTwitter API v2とPythonを使用して、自動ツイートをする内容でした。

他にもTwitterにて、手作業でできる作業はこちらのAPIを使用して比較的容易に作業を自動化できそうなので、今後も何か作成していこうかと思います。

完成したらまた紹介していきます。

なお、弊社ではこのように業務改善の一環として自動化に関するソリューションを提供しています。

「こんな作業を自動化したい・できるのか?」等、業務効率化に関するご相談があれば、問い合わせからお気軽にご連絡下さい。