39
43

More than 5 years have passed since last update.

分析目的のTwitterデータ収集方法(Python・TwitterAPI)

Posted at

※2019年3月時点の情報です

Twitterデータを分析しようと思い、データ収集方法を調べました。
地味に色々なサイトを見て回ることになったので備忘録としてまとめておきます。

準備

Twitterは事前の承諾なしのスクレイピングを禁止しているので、APIを使う必要があります。

Twitter APIの登録については以下の記事がわかりやすいです。
Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ

300文字の英作文では以下の記事が役に立ちました。
TwitterAPIの申請に必要な英作文をユルく和訳してみた

私の場合、新規に作成したアカウントで申請から4時間程度で承認されました。

収集

使うライブラリ

  • OAuth1Session
  • twitter
  • python-twitter
  • tweepy

などからどれか好きなもの。どれを使っても大差はないと思います。
今回は一番使用例が多いように感じたOAuth1Sessionを使います。

APIを投げるURL

https://api.twitter.com/1.1/search/tweets.json?tweet_mode=extended
末尾に?tweet_mode=extendedをつけない場合、ツイートが140文字を超えると省略されたものが取得されてしまいます。

シンプルな取得コード例

from requests_oauthlib import OAuth1Session

# トークン情報
CONSUMER_KEY = 'xxxxxxxxxx'
CONSUMER_SECRET = 'xxxxxxxxxx'
ACCESS_TOKEN = 'xxxxxxxxxx'
ACCESS_TOKEN_SECRET = 'xxxxxxxxxx'
# OAuth認証
api = OAuth1Session(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)

# 「hogehoge」が含まれるツイートを5つ取得
url = 'https://api.twitter.com/1.1/search/tweets.json?tweet_mode=extended'
params = {'q': 'hogehoge', 'count': 5}
req = api.get(url, params=params)

Twitter開発者ドキュメント日本語訳
公式ドキュメントの日本語訳があるので非常に参考になります。
ただしドキュメントに書かれていない検索術などがあるようです。

  • params

paramsで検索条件を設定します。
クエリの具体例は以下がわかりやすいです。
https://gist.github.com/cucmberium/e687e88565b6a9ca7039

  • 戻り値req
    • ステータス部 req.status_code
    • ヘッダ部 req.headers
    • テキスト部 req.text

正常に取得できている場合、取得ステータス(req.status_code)の値は200です。
取得ツイート情報はreq.textに指定数(count)分だけjson形式で入ります。
JSONの例は以下です。
https://github.com/twitterdev/tweet-updates/blob/master/samples/initial/extended_extended_14001.json

サンプルコード

ハッシュタグhogehogeが含まれるツイートをリツイートを除外して新しいものから順に取得できるだけ取得。
取得したデータはPandasのDataFrameにしてPickleで保存。

import os
import time
import json
import pandas as pd
from requests_oauthlib import OAuth1Session

CONSUMER_KEY = 'xxxxxxxxxx'
CONSUMER_SECRET = 'xxxxxxxxxx'
ACCESS_TOKEN = 'xxxxxxxxxx'
ACCESS_TOKEN_SECRET = 'xxxxxxxxxx'

class TwitterApi:

    def __init__(self, search_word, count):

        self.twitter_api = OAuth1Session(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)               
        self.url = 'https://api.twitter.com/1.1/search/tweets.json?tweet_mode=extended'
        self.params = {'q': search_word, 'count': count, 'result_type': 'recent', 'exclude': 'retweets'}
        self.tweet_num = count

    def get_next_tweets(self):
        req = self.twitter_api.get(self.url, params=self.params)

        # 正常に取得できている場合
        if req.status_code == 200:

            self.x_rate_limit_remaining = req.headers['X-Rate-Limit-Remaining']
            self.x_rate_limit_reset = req.headers['X-Rate-Limit-Reset']

            self.tweets = json.loads(req.text)

            self.tweet_num = len(self.tweets['statuses'])
            if self.tweet_num == 0:
                return True

            self.max_id = self.tweets['statuses'][0]['id']
            self.min_id = self.tweets['statuses'][-1]['id']
            next_max_id = self.min_id - 1
            self.params['max_id'] = next_max_id

            return True

        else:
            return False

# 検索語
search_word = '#hogehoge'
count = 100

twitter_api = TwitterApi(search_word, count)

tweets_df = pd.DataFrame([])

while twitter_api.tweet_num > 0:
    ret = twitter_api.get_next_tweets()

    if twitter_api.tweet_num == 0:
            break

    if ret:
        # PandasのDataFrameに変換
        df = pd.io.json.json_normalize(twitter_api.tweets['statuses'])
        tweets_df = pd.concat([tweets_df, df], axis=0)

        print('アクセス可能回数:', twitter_api.x_rate_limit_remaining, ' リセット時間:', twitter_api.x_rate_limit_reset)

    else:
        # エラー時はとりあえず60秒待って再取得
        print('Error!, Wait 60s...')
        time.sleep(60)

# ツイート日時列をTimeStamp型にして降順に並び替え、Pickle保存
tweets_df['created_at'] = pd.to_datetime(tweets_df['created_at'])
tweets_df = tweets_df.sort_values('created_at').reset_index(drop=True)
tweets_df.to_pickle('saved_tweets_df.pickle')

本当はアクセス可能回数やリセット時間をちゃんと見て再取得するべきですが、それらが正常に取得できない場合があるみたいなのでひとまず適当に再取得しています。
ツイートIDは新しいものほど大きな値が振られているので、再取得時には前回取得した最小IDの値より小さいmax_id条件を設定します。

その他参考

末尾に?tweet_mode=extendedをつけない場合のツイート取得
http://ailaby.com/twitter_api/#id7_2

39
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
43