ホーム
記事一覧
プライバシーポリシー
免責事項
お問い合わせ

PythonとTwitter APIを利用したツイート収集方法

2020-03-20
2020-05-09

PythonとTwitter APIを使ってTwitterの分析を行いたいと思ったので、Twitter APIについて色々調べて試してみました。

Twitter APIとは、公式の言葉を引用すると以下のようなものです。

Twitterにある情報をできるだけ広く共有するために、API (アプリケーション・プログラミング・インタフェイス)を通してTwitterデータにプログラムレベルでアクセスし、企業、開発者、利用者に提供します。 引用:TwitterのAPIについて

今回はこのTwitter APIの概要とPythonを利用したSearch Tweets APIの使い方についてまとめました。

Twitter APIでできること

Twitter APIではTwitterでできることはほぼ全てできます。 詳細はこちらのドキュメントに記載されています。

APIを使うことで、Twitterでできることをある程度自動化できることがアプリと比較したメリットです。

例えば、Twitterのサードパティーサービスのようにツイートの予約・自動投稿が可能になります。まぁ、だいたいやりたいと思ったことはコードとAPIを組み合わせれば実現できそうです。

ただし、開発者が守るべき自動化ルールがあるので、自動化のプログラムを使用する前に確認しておきましょう。

今回使用するのは、ツイートの収集なのでSearch Tweets APIを利用します。

Twitter API の始め方

Twitter APIを使用するには、Twitterのアカウントの他にTwitter APIの登録申請が必要です。

詳しいやり方はこちらの記事が大変参考になります。

ポイントは申請内容はすべて英語で書く必要があることです。

とはいえ、私たちにはGoogle翻訳があるのでそこまで苦労することはないです。日本語で内容を書いて、Google翻訳の結果をコピペすれば大丈夫です。

書く内容については、正直に書けば問題ないと思います。

私の場合は以下のような内容で申請しました。

私がtwitterデータを利用する理由は以下の2つです。 1つ目は自分のブログに関連するトピックの分析です。twitterの情報を分析し、ユーザーに需要のある記事を書きたいと思ってます。 2つ目は機械学習のためのデータ収集です。私は、機械学習を勉強中で生データを使った分析を試してみたいと思ってます。

申請結果は申請してすぐにきました。他の記事では1日やそこら待つとありましたが、私の場合は出してすぐにメールがきました。普通に書いて出せば、その日のうちに利用を開始できると思います。

利用できるようになったら必ず開発者契約およびポリシーは確認しましょう。

Search tweets APIの制限

APIが使えるようになったら早速試したいところですが、APIにはいろいろ条件があるのでまずはそれらを確認します。

Seatch Tweets APIにはStandardPremiumEnterpriseの3タイプがあります。3タイプの比較についてはこちらの記事が参考になります。

今回利用するStandard Search APIには以下のような制限があります。

  • 15分間に180リクエストまで
  • 1度に取得できるツイート件数は100件
  • 遡れる期間は7日前まで

他の制限やSearch APIのパラメータなどについてはこちら(公式)に記載されてます。

コードを書くまえにcurlを利用したexampleがあるので、そちらを試すとイメージが掴めます。

Pythonでツイートを取得する方法

いよいよAPIを利用してツイートを取得していきます。

今回はPythonを使ってAPIを叩きます。PythonにはtweepyというTwitter API用のライブラリがあるのでそちらを利用します。

ちなみに今回の検証環境は以下になります。

  • MacOS Mojave バージョン10.14.6
  • Python 3.7.4

コードは以下のようにしました。あまり綺麗な書き方じゃないかもしれません。。

必要ないかもしれませんが、リクエスト前にsleepを適当に設定しました。

import tweepy
import pandas as pd
import datetime
from time import sleep
import argparse

parser = argparse.ArgumentParser(description='Twitter APIでツイート取得')
parser.add_argument('-q', help='検索クエリ')
parser.add_argument('--cnt',default=100, help='取得件数。デフォルト100件')

args = parser.parse_args()

# API認証情報
CONSUMER_API_KEY = ""
CONSUMER_API_SECRET_KEY = ""
ACCESS_TOKEN = ""
ACCESS_TOKEN_SECRET = ""

# tweepyでTwitter APIラッパーオブジェクト取得
def getAPI():
    auth = tweepy.OAuthHandler(CONSUMER_API_KEY, CONSUMER_API_SECRET_KEY)
    auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)

    api = tweepy.API(auth)

    return api

# ツイートを取得
def getTweetData(api):

    tweet_data = []

    try:
        response = api.search(q=args.q, count=1, result_type="result_type", lang='ja',tweet_mode='extended')
    except tweepy.error.TweepError as tweepy_error:
        print(tweepy_error)

    next_max_id = response[-1].id

    i=0
    sleep(1)

    while True:
        print('検索ページ:' + str(i))

        try:
            response = api.search(q=args.q, count=100, max_id=next_max_id-1, lang='ja',tweet_mode='extended')

            if len(response) > 0:
                next_max_id = response[-1].id
            else:
                print("これ以上取得できません。検索ツイートが7日以上前か、検索ボリュームが少なすぎます。")
                break

            for tweet in response:
                user_mentions = []

                if tweet.entities["user_mentions"]:
                    for name in tweet.entities["user_mentions"]:
                        user_mentions.append(name["screen_name"])

                mention_names = ','.join(user_mentions)

                tweet_data.append([tweet.created_at.strftime('%Y/%m/%d'), tweet.id, tweet.user.name, tweet.user.screen_name, tweet.full_text.replace('\n',''), tweet.favorite_count,tweet.retweet_count,tweet.user.followers_count,tweet.user.friends_count,mention_names])

        except tweepy.error.TweepError as tweepy_error:
            print(tweepy_error)
            break
        except tweepy.error.RateLimitError as limit_error:
            print("検索上限に達しました")
            break

        i+=1
        if(i == 180):
            print("検索上限に達しました。上限は15分後にリセットされます")
            break
        sleep(2)

    print("Finish search!")

    return tweet_data

def makeFile(data):
    now = datetime.datetime.now()
    q = args.q.replace(' ', '_')

    # 結果保存パス、ファイル名
    file_name = 'path/{0}_{1}.csv'.format("query", now.strftime('%Y-%m-%d_%H-%M'))

    columns = ["投稿日", "ID", "User_name", "Screen_name", "text", "favorite", "retweet_count", "followers", "follows", "user_mentions"]

    df = pd.DataFrame(data) # 行の名前を設定
    df.columns = columns

    df.to_csv(file_name)

if __name__ == "__main__":
    api = getAPI()
    search_data = getTweetData(api)
    makeFile(search_data)

認証情報はAPI利用申請を行い、APIを使うアプリケーションの登録を行うと取得できます。

tweepyを使えば上記のようにAPIのラッパーを簡単に扱えます。

検索クエリはコマンドラインから引数として渡します。検索結果はpandasを利用してcsvにまとめます。今回は取得した情報全てではなく、いいね回数やフォロワー数などなんとなく役に立ちそうなものを抜粋しました。

このコードのポイントは以下の通りです。

  • tweet_mode='extended'を指定
  • ツイートのidを保持し、2回目の以降の検索はそのid以降からツイートを取得
  • ツイートに含まれるメンションを保存

1つ目のtweet_mode='extended'は指定しないと、文字数が多いツイートの文章が省略されてしまいます。指定することでツイート全文を得られます。 気をつけないといけないのは、tweet_mode='extended'を指定しない場合では、ツイート文の取得キーがtweet.full_textではなくtweet.textになります。

2つ目のidは、2度目にAPIを叩く時に1度目に取得したツイート以降の結果を取得するために利用します。Search Tweets APIは1度に100件までなので、重複せずに結果を取得するために必要になります。

3つ目は、取得したツイート文に含まれるメンションを後で抜くために使います。正規表現で抜いてもいいのですが、APIの結果を利用した方が確実なのでこちらを利用します。

実行するときは以下のようにターミナルに入力します。

python <ファイル名>.py -q "<検索文>"

エラーなく終了すると、makeFile関数で指定したパスに結果がCSVで保存されます。

検索クエリのオプション

Search Tweets APIではTwitterアプリの高度な検索と同じように検索に条件を設定できます。この設定を行うと、後でツイート文を分析するときにコード上で行う処理が減るので便利です。

公式ではStandard search operatorsと呼ばれています。

よく使うのをいくつ紹介します。先頭にハイフンがついてるオプションは否定を意味します。

  • lang:ja 日本語のみ取得
  • -filter:links URLを含むツイートを除外
  • -filter:retweets リツイートを除外
  • -from:アカウント名 アカウント名のツイートを除外
  • hoge -huga hogeを含むがhugaは含まないツイート

これらのオプションをコード実行時の検索クエリに含めると指定した条件に合致したツイートのみが取得できます。

まとめ

今回はTwitter APIのSearch Tweets APIについて紹介しました。

ツイートはデータ分析をする上で非常に役立ちます。とくに自然言語処理を勉強する上で、大量の生データを扱えるのはありがたいです。

ツイートは本当にいろいろなパターンがあるので、自然言語処理の前処理の勉強にはもってこいです。

次回は今回のコードを利用したツイート収集自動化について書こうと思います。

参考書籍

APIについては以下の書籍が参考になりました。


Pythonを使ったAPI操作は以下の書籍を参考にしました。スクレイピングや機械学習についても書かれており重宝してます。私が持っているものの増補改訂版が出てたのでそちらを紹介します。