TwitterAPI でツイートを大量に取得。サーバー側エラーも考慮(pythonで)

TwitterAPI を利用してツイートを大量にダウンロードしてみます。ダウンロードしたツイートを MeCab や Word2vec の元ネタにするつもりですが、とりあえず、データ取得の部分にしぼって書いてみます。

前半は API の基本事項の説明なので、そんなのもう知ってるよ、な方は 後半の 「大量にダウンロード」 にとんでください。

- 目次 -

スポンサーリンク

TwitterAPI とは

ツイートを投稿、閲覧するための API です。簡単に利用できるので、ツイッターにアクセスする独自アプリケーションを手軽に作成できます。

TwitterAPI を利用するには

  • アプリケーションの登録
  • 4つの認証キー取得

が必要にになります。
手順はいろいろなサイトで紹介されていますが、たとえば ここ で確認できます。

仕組み

REST形式で要求を出し、JSON形式で結果を受け取るのが基本的な仕組みです。用途に応じて様々なエンドポイントが定義されており、パラメータもそれぞれ異なります。いくつか例をあげると

●キーワードを指定してツイートを取得したければ

URL https://api.twitter.com/1.1/search/tweets.json
必須パラメータ q : 検索ワード

●特定ユーザーのツイートをまとめて取得したければ

URL https://api.twitter.com/1.1/statuses/user_timeline.json
必須パラメータ user_id : ユーザーID
 または
screen_name : スクリーン名(@で表示される名称)

●ツイートを投稿したければ

URL https://api.twitter.com/1.1/statuses/update.json
必須パラメータ status : 投稿ツイート

オプションのパラメータとして

  • count
    取得件数を指定します。
  • max_id
    ツイートID の最大値を指定します。
    大量のツイートを取得する場合、一度に取得できるツイート数は限られているので、何度もリクエストを出すことになります。その際 max_id を指定すると、前回取得したツイートの次からを取得対象にできます。

取得データ

取得データは ステータスコード、ヘッダー部、テキスト部に別れます。

ステータスコード

API 呼出しの正常・異常終了はステータスコードで判定します。200 が正常終了を意味します。

ヘッダー部

ヘッダ部には以下に説明する制限情報がのっています。

制限情報とは

TwitterAPI には一定時間内にアクセスできる回数に上限があります。
たとえば、キーワードで検索する

https://api.twitter.com/1.1/search/tweets.json

は 15 分間に 180 回までと決まっており、この規定回数を超えてアクセスするとエラーになります(コード:429)。もちろん永遠にアクセスできないわけではなく、15 分毎にアクセス制限はリセットされます。

そうした制限に関する情報がヘッダ部にのっており、以下のキーで取得できます。

  • X-Rate-Limit-Remaining
    アクセス可能回数 (アクセスするごとに -1 されていきます)
  • X-Rate-Limit-Reset
    アクセスが可能になるまでの時間 (アクセス可能回数が 0 になっても、この値の時間まで待てば回数はリセットされます)

補足

制限情報を確認するための専用エンドポイントもあります。
https://api.twitter.com/1.1/application/rate_limit_status.json

一発目の検索前にアクセス可能回数を調べるという手堅い実装をするなら、このエンドポイントが便利です。
こちらのソース の checkLimit で使ってます。

テキスト部

取得したツイートはテキスト部にのっています。テキスト部のフォーマットはエンドポイントによって差異があるので、ツイートを取り出す際は注意が必要です。
たとえば

  • キーワード検索(https://api.twitter.com/1.1/search/tweets.json)の場合
    ⇒ テキスト部の statuses の下にツイートが置かれる
  • ユーザー名で検索(https://api.twitter.com/1.1/statuses/user_timeline.json)の場合
    ⇒ テキスト部の直下にツイートが置かれる

という違いがあります。

取得データ フォーマットイメージ

以下はキーワード検索時の取得データのフォーマット(ごく一部の抜粋)です。ユーザー名で検索した場合は statuses という項目そのものが存在せず、テキスト部直下にツイートがぶら下がっています。
twitter APIのレスポンス

retweeted_status は
リツイート時のみセットされる

コピペ用

status_code
headers
┗ X-Rate-Limit-Remaining
┗ X-Rate-Limit-Reset
text
┗ statuses
   ┗ text
   ┗ id
   ┗ user
     ┗ screen_name
     ┗ followers_count
   ┗ created_at
   ┗ retweeted_status
     ┗ text
     ┗ id

サンプル

簡単なサンプルをコーディングしてみます。

ツイート取得

以下で、”沖縄旅行” を含むツイートを 10 件取得できます。

ツイート投稿

投稿は以下で OK。

◇◇◇

基本事項の説明はここまでです。次節でデータのダウンロードに取りかかります。

大量にダウンロード

ここからが本題ですが、ツイートを大量に取得するためのプログラムを作ります。一回に取得できる件数は 100 とか 200 件程度の上限があるので、ループしながら API 呼出しを繰り返すことになります。ただし、回数制限があるので、ひたすら API を呼び続けるわけにはいかず、考慮が必要です。

方針として

  • 「キーワードで取得」 と 「ユーザーを指定して取得」 の2機能を備える
  • ツイートは一件づつ yield する
  • 回数制限に到達したら、制限解除まで sleep し、解除後に再開する

ことにします。

クラスは3つ。

TweetGetter クラス図

ソース

このまま実行すれば “渋谷” をふくむツイートが 3000 件取得できます。
コメントを入れ替えれば “AbeShinzo” さんのツイートが取得できます。

オプション

collect メソッドの引数で以下の 3 点が指定可能。

  • total : 取得件数
    デフォルト -1 (無制限に取得。ただし Twitter 側の設定する上限がある)
  • onlyText : メッセージ本文だけ取得する
    デフォルト False
  • includeRetweet : リツイートを含める
    デフォルト False

エラー対策

サーバー側に起因するなんらかの理由でエラーが発生する場合があります。以下、対処法です。

Service Unavailable

status_code:503

サーバー側の処理が追いつかない場合に発生します。しばらく sleep してアクセスを再開すれば問題ありません。必要な sleep 時間はサーバーの状況によると思いますが、今まで見た範囲では 30 秒の sleep で大丈夫でした。

Too Many Requests

status_code:429

180回/3分 等の回数制限を無視してアクセスすると発生します。
X-Rate-Limit-Remaining を確認しながらアクセスすれば通常は発生しません。

正しい手順として、X-Rate-Limit-Remaining が 0 になった場合は X-Rate-Limit-Reset まで sleepします。ただし、sleep 時間が微妙にサーバーとずれる可能性があるため、アクセスを再開する前に下記のエンドポイント

https://api.twitter.com/1.1/application/rate_limit_status.json

remaining (アクセス可能回数)
reset        (アクセスが可能になるまでの時間)

を確認します。

X-Rate-Limit-Remaining が入ってない

理由は不明ですが、レスポンスに X-Rate-Limit-Remaining が入ってないことが稀にあります。そうしたケースでは、下記のエンドポイント

https://api.twitter.com/1.1/application/rate_limit_status.json

remaining (アクセス可能回数)
reset        (アクセスが可能になるまでの時間)

を確認します。

スポンサーリンク
その他の記事
    • あ、抜けてますね。しかも、ところどころ。。。

      直しました。

      2.7 で動かしてるので、すぐ括弧を忘れてしまいます。
      ありがとうございました。

  1. プログラム大変参考にさせてもらっています。
    質問なのですが
    idを取得してidの人の自己紹介文を取得することは可能ですか?

    • こんな感じでしょうか。

      ① ツイートから id を取得する
      tweet['id']

      ② id からユーザー情報を取得する(別途、リクエスト)
      url = 'https://api.twitter.com/1.1/users/show.json'
      params = {'user_id':'xxxxxxxxx'}
                   ↑
                 ①で取得したやつ

      res = session.get(url, params = params)

      ③ 自己紹介を取りだす
      t = json.loads(res.text)
      print (t['description'])

      ======================
      ちなみに

      安倍さんの自己紹介はこれで取得できました。

      url = 'https://api.twitter.com/1.1/users/show.json'
      params = {'user_id':'468122115'}
      res = session.get(url, params = params)

      t = json.loads(res.text)
      print (t['description'])

  2. 分かりやすい記事をありがとうございます。

    大量にツイートを取得する際は最近のツイートしか取得できないという使用でしょうか。

    キーワードによっては取得件数が少ししか取れないものもあるようでして

    お願いします。

    • tas さん、どうも。

      ネットの情報ですが、APIでは過去1週間のツイートしか取れないようです。
      キーワードによっては、ほとんどツイートがないケースもあるかもしれませんね。

  3. 管理人様

    回答頂きありがとうございます。
    ツイートID で過去の記事を取得するとかありますね。

    streamingAPI をずっと動かしつづけるしかないのでしょうか・・・(T_T)

  4. 管理人様
    tweetの投稿された位置情報(投稿場所情報)を同時に取得するにはどのようにすればよろしいでしょうか?

    • yuさん、こんにちわ

      coordinates という項目に経度、緯度が入るようです。
      掲載ソースの場合、こうなります。(インデントがうまく入ってませんが)

      if tweet['coordinates'] is not None:
      print (tweet['coordinates']['coordinates'][0]) # 経度
      print (tweet['coordinates']['coordinates'][1]) # 緯度

      位置情報付きでつぶやく人は少ないので、実際に coordinates に値が入るツイートも少ないようです。

  5. はじめましてこんにちは。
    自分は研究でTwitterのツイート内容の解析について勉強中なのですが、テキストに実行結果を出力する方法がいまいちわからないので教えていただけませんか?

    • SUSUMUさん、こんにちは
      テキストファイルに出力ということでしたら、こんな感じでできると思います。
      for ループのインデントが入ってませんが、そこは付け足してください(f.write の箇所)。

      import codecs

      getter = TweetsGetter.bySearch(u'渋谷')

      f = codecs.open('/tmp/tweets.txt', 'w', 'utf-8')

      for tweet in getter.collect(total=3):
      f.write('——————————————–')
      f.write('\n')
      f.write(str(tweet['id']))
      f.write('\n')
      f.write(tweet['created_at'])
      f.write('\n')
      f.write(tweet['user']['screen_name'])
      f.write('\n')
      f.write(tweet['text'])
      f.write('\n')

      f.close()

      • こちらのプログラム私も参考にさせて頂いているのですが以下のようなエラーが改善できません。
        Traceback (most recent call last):
        File "text.py", line 242, in
        f = codecs.open('/tmp/tweets.txt', 'w', 'utf-8')
        File "C:\Program Files\Python35\lib\codecs.py", line 895, in open
        file = builtins.open(filename, mode, buffering)
        FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tweets.txt'

        何かお力添え頂ければ幸いです。

  6. 管理人さま
    とてもわかりやすい記事をありがとうございます.
    当方超初心者で野暮な質問だとは重々承知なのですが
    Twitter Streaming APIとはまた別のAPIなのでしょうか?
    それとも上記APIをPHPではなくPythonで動かしてみた,とうことなのでしょうか?

    • renaco さん、こんにちわ。

      ここで紹介した TwitterAPI は過去のツイートを取得するものです。

      Twitter Streaming API は、今現在つぶやかれたツイートをリアルタイムで取得するものです。動かしっぱなしにしとけば最新ツイートがどんどん送られてきます。

      • インデントが入ってないですけど、Streaming はこんな感じで動くようです。

        import requests
        import json
        from requests_oauthlib import OAuth1

        CK = '8uYOL8qfRB—————'
        CS = 'HFIcvU2nCB—————————————-'
        AT = '104137178—————————————–'
        AS = '4ViVoEMdiH———————————–'

        url = "https://stream.twitter.com/1.1/statuses/filter.json"

        auth = OAuth1(CK, CS, AT, AS)

        r = requests.post(url, auth=auth, stream=True, data={'track' : u'渋谷'})

        for line in r.iter_lines():
        if len(line) == 0:
        continue

        tweet = json.loads(line)
        print ('—————- ')
        print ('{} {}'.format(tweet.get('created_at'), '@'+tweet.get('user').get('screen_name')))
        print (tweet.get('text'))

  7. 初めまして。
    こちらのプログラム大変参考にさせて頂いております。
    初心者の質問で申し訳ないのですが、取得したツイートを形態素解析してExcelで表にしたいと考えているのですが、こちらにそういったプログラムを組み込む事は可能でしょうか?
    もし可能であれば、方法等ご教授頂けますと幸いです。

    • aris さん、こんにちわ。

      形態素解析は janome を使うのが手軽だと思います。
      excel出力はやったことがないのでよく分かりませんが、検索すればいろいろなライブラリが出てくるようです。

      どんな表を作るのかにもよりますが、大体こんな流れではないでしょうか。

      ① tweet['text']を janome に渡して単語に分解、
      ② その結果を集計(単語のカウント等)
      ③ excel に出力

  8. お返事遅れて申し訳ありません。
    色々解説下さりありがとうございます。
    janome等調べて試行錯誤してみようと思います。
    また知恵をお貸しいただければ幸いです。

  9. わかりやすい記事で初心者の私も大変参考になっています。
    質問なのですが画像付きのツイートのみを取得し画像のidを取得するといったことは可能でしょうか?

    • ggさん、こんにちわ。

      詳細は未確認ですが、検索キーに filter:media と付け加えると画像や動画付きのツイートが取得できるようです。

      getter = TweetsGetter.bySearch(u'渋谷 filter:media')

  10. 初心者でもわかりやすい記事で参考にさせていただいており、大変勉強になります。
    お忙しいところ大変申し訳ないのですが、プログラム作成に手こずっており、自分で解決する事ができなかったため、教えていただければと思いコメントさせていただきました。
    現在、ツイートを30000件取得し、ツイート3000件ずつテキストに保存をするプログラムを組もうとしています。
    管理人様のプログラムを実行するとAPIアクセス回数は100件に2回〜3回ほどなのですが、下記のプログラムのようにif文を付け加えると極端に増えて10回以上アクセスしてしまい、ツイートを取得するのに時間がかかってしまいます。アクセス回数を減らすにはどうしたらいいでしょうか、お時間あるとき二返信くださると大変助かります。

    if __name__ == '__main__':
    # キーワードで取得
    getter = TweetsGetter.bySearch(u'リセット')
    cnt2 = 1
    cnt = 0
    cnt3 = 0
    count = 0
    f = codecs.open('tweet.txt', 'w')
    for tweet in getter.collect(total=30000):
    cnt += 1
    cnt3 += 1
    f.write('————————————-'+str(cnt))
    f.write('\n')
    f.write(tweet['text'].strip())
    f.write('\n')
    if cnt % 3000 == 0 and not(cnt3 ==30000):#3000件ごとにファイルを作る、3000件目はテキストファイルを作らない
    cnt2 += 1
    cnt = 0
    f.close
    f = codecs.open('tweet'+str(cnt2)+'.txt', 'w')#次のファイルに移るときcnt2をカウントしてファイル名にする
    elif cnt3 == 30000:
    f.close
    else:#if文実行何回で1回アクセスしているかみる
    count += 1
    print(count)
    f.close

    • ymk さん、こんにちわ。

      拝見したところ、else の処理は cnt が 1 から 2999 の場合、常に通るように見受けられます。ということは、closeしたファイルに write していることになります。

      その辺が影響して挙動がおかしくなっているのではないでしょうか。

  11. 大変わかりやすい記事をありがとうございます。
    tweetを大量に取得したいと思い、collectのtotal=500,000にしてみたところ、wait表示が表示されず、9400件ほどしか取れていないのに関わらずプログラムが実行完了してしまいます。
    mongoの方の問題だとも思ったのですが、DB名を変えても同様の動作になってしまいます。また、一週間分しかAPIでは取れないからかとも考えたのですがtotal=50,000だと問題なく動くのでこれも原因ではないと思いました。どうしたら挙動が改善するのかお時間のある時にでもアドバイスをいただけると嬉しいです。

    • さく さん、こんにちわ。

      もしエラー表示がない状態で終了したのならデータがそれだけしかなかったのだと思いますが ??? ちょっと判りかねます ???

      • 管理人さま
        早速のご返信ありがとうございました。
        また、別件なのですがcollectの値を指定しなければ一週間分の全データを取得することは可能でしょうか?
        度々質問をしてしまい、申し訳ありません。

  12. 初めまして。
    現在独学でpythonのスクレイピングを学んでいたところでしたので、
    掲載頂いた記事がとても分かりやすく非常に感謝しております。
    「大量にダウンロード」の章で記載いただいたプログラムを自分で作成してみたところ、
    以下のエラーがどうしても消えず、困っています。。
    requests.exceptions.MissingSchema: Invalid URL 'https//api.twitter.com/1.1/application/rate_limit_status.json': No schema supplied. Perhaps you meant http://https//api.twitter.com/1.1/application/rate_limit_status.json?

    URLが有効ではないエラーなのかなと思っているのですが、
    どのように改善したら良いか私の方では分からない状況でして、、
    エラーの回避方法についてもし何かお分かりでしたらご教授いただけますと大変助かります!

  13. こんにちは。
    python学習中のため、いつも参考にしております。
    一つお聞きしたいのですが、このプログラムに「リツイート数」、「いいね数」
    を実装することは可能でしょうか。

    • まさおかさん、こんにちわ

      twitter の以下サイトにAPI検索で取得可能なデータが載っています。

      ttps://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets

      「Example Response」に記載があれば、取り出すことができます。

  14. 管理人 様

    はじめまして。基礎から勉強中のpython初心者です。
    Twitterの分析をしたくこのプラグラムにたどり着きました。

    大量にダウンロードのコードを使用して取得は出来るのですが、
    結果をtextに吐き出したく、以前の質問に同内容を拝見しましたが、
    どこにwrite等のtext書き込みコードを入れて良いのかご教示お願いします。
    色々調べたのですが、、初歩的な質問ですいません。
    何卒、宜しくお願いします。

    • takenoko さん、こんにちわ

      '__main__' 以下を

      http://ailaby.com/twitter_api/#comment-2671 の内容で置き換えれば動くと思います。
      (事前にtmpディレクトリを作ってから)

      • 管理人 様

        ご返信ありがとうございます。以下に書き換えてみましたが動かず。。
        置き換えの方法や記述の仕方に問題があったのか、度々申し訳ございません。

        ご指摘頂けますと幸いです。以下アフターの235行以下コードになります。

        if __name__ == '__main__':

        import codecs

        getter = TweetsGetter.bySearch(u'渋谷')

        f = codecs.open('/tmp/tweets.txt', 'w', 'utf-8')

        for tweet in getter.collect(total=1000):

        f.write('——————————————–')
        f.write('\n')
        f.write(str(tweet['id']))

        f.write('\n')
        f.write(tweet['created_at'])
        f.write('\n')
        f.write(tweet['user']['screen_name'])
        f.write('\n')
        f.write(tweet['text'])
        f.write('\n')

        f.close()

        • ファイル出力がうまくいかないようですが、原因はちょっと判りかねます。その辺に関するノウハウはネット上で十分得られると思いますので、そちらを参考にしてください。まず基本的な知識を習得されるのが早道かと思います。

  15. 管理人様
    こちらのコードを参考にコードを作成したところ、非常に参考になり助かりました。
    1点伺いたいのですが、複数条件を指定する(たとえば、"渋谷"かつ"ハチ公")場合、」どのように記述すればよいのでしょうか?

  16. 初歩的な質問で申し訳ないのですが、jsonのimportができません。
    ターミナルからのぱけーじインストールコマンドは何を使っているか教えていただきたいです。

    • python2.7 には最初から json が入っているようです。python の古いバージョンの場合は simplejson というものをインストールするそうです。詳しくはネットで検索してみてください。

  17. 潜水艇金槌 says:

    管理人様

    はじめまして。
    素人質問で恐縮なのですが,一点ご教示願えませんか?

    「APIで収集できるのは1週間分」とのことですが,
    1週間分のデータを収集し終えた後も,
    引き続き新たなtweetを取得し続けるように
    することもできるのでしょうか…?

    急ぎませんので,ご都合のよろしいときに
    ご教示いただけますと幸いです。

    • 潜水艇金槌さん、こんにちわ。

      質問の意図と少し違うかもしれませんが、Streaming API を使うと最新のツイートをリアルタイムで取得し続けることができます。

      こちらで少し触れています。
      http://ailaby.com/twitter_api/#comment-3284
      http://ailaby.com/twitter_api/#comment-3285

      • 潜水艇金槌 says:

        管理人様

        こんにちは。
        お忙しい中,お返事いただいたにもかかわらず,
        こちらからの反応が遅くなってしまい申し訳ありません。

        ご丁寧にご教示下さりありがとうございます。
        Streaming APIは6月に使えなくなるという話を風のうわさで聞いたのですが,
        これに代わるものなどご存知ないでしょうか…?
        (また,実際に使ってみたのですが,「全体の1%」からtweetを取得しているためか,思ったほどのデータが得られず…)

        こちらに関しましても,
        ご都合のよろしいタイミングでご教示いただけますと幸いです。

  18. 管理人様

    はじめまして。
    現在研究のためにツイートを集めています。
    そのなかで管理人様の作成したプログラムを参考にしました。
    本当にありがとうございます。

    今回は質問があり連絡させていただきました。
    管理人様のプログラムを複数のユーザーのツイートを順次取得していくように変更しました。
    そのなかでToo Many Requestsでエラーが起こります。(関数checkLimit内のif res.status_code != 200)
    エラー対策として管理人様が remaining 、resetを確認すると書いていますがどうすればプログラムを変更したらいいのかわかりません。
    速度制限でエラーを起こさず、可能になるまで待つ様に変える為にはどうしたらいいでしょうか。
    ご多忙のところ恐縮ですが、ご返答いただければ幸いです 。

    よろしくお願い致します。

    • はなさん、こんにちわ。

      > エラー対策として remaining 、resetを確認する

      これは、tweets.json または user_timeline.json の取得で Too Many Requests が発生した場合の対策です。rate_limit_status.json に関しては当てはまりません。

      あまりキレイなやり方ではありませんが、Too Many Requests 発生時に15分以上の sleep を入れて continue すれば、とりあえず動くと思います。

      ただ、このやり方だと sleep が頻発するかもしれません。

      キレイに直すとすれば、TweetsGetter.byUser の引数としてユーザー名の配列を渡し、collect 内部でユーザー名を切り替えていく形が考えられます。こちらは大がかりな修正になりそうですが。。。

      • 管理人様

        こんにちは。
        お早い対応有難うございます。
        さらにとても分かりやすく教えて頂いて、重ねて心より感謝申し上げます。

        >TweetsGetter.byUser の引数としてユーザー名の配列を渡し、collect 内部でユーザー名を切り替えていく形

        こちらはcollect内を変更するのは怖くて出来ないので諦めます。。。
        提案してくださったのに申し訳ありません。ありがとうございます。

        >Too Many Requests 発生時に15分以上の sleep を入れて continue
        こちらを行おう為に下記の様に変更しました。

        if res.status_code == 429:
        time.sleep(900)
        continue
        elif res.status_code != 200:
        raise Exception('Twitter API error %d' % res.status_code)

        教えて頂いた方法とあっているか不安ですが、
        今のところエラーを起こさず動き続けています。本当にありがとうございます!

        ご迷惑をおかけしないように頑張りますが、
        また質問が出来てしまった際にはどうかよろしくお願いいたします。

  19. 管理人様

    こんにちは。
    またの質問失礼いたします。
    今日またツイートを取得しようと思い実行したところ下記のエラーが起こりました。
    意味がわからなかった為とりあえずもう一度実行したところ動きました。
    しかし途中でエラーが起こりました。同様のエラー文でした。
    File "autosearch.py", line 107, in collect
    self.checkLimit()
    File "autosearch.py", line 136, in checkLimit
    remaining, reset = self.getLimitContext(json.loads(res.text))
    File "autosearch.py", line 193, in getLimitContext
    remaining = res_text['resources']['search']['/search/tweets']['remaining']
    KeyError: 'search'
    このエラー文はどういことでしょうか?
    ツイートを取得しすぎてAPI側が制限をかけてきているのかなとヒヤヒヤしています。。。

    お忙しいとは思いますが、ご返答いただければ幸いです 。
    よろしくお願い致します。

    • KeyError: 'search' は、レスポンスの json 内に search 要素が無いという意味です。

      ユーザーを指定してツイートを取得する …ByUserクラス を動かしているのだと思いますが、エラーの発生個所はキーワードで検索する …BySearchクラス 側のようです。ちょっと変ですね。

      継承関係がおかしくなってるのかもしれませんが、詳しい原因はよくわかりません。修正箇所を見直してみてください。

      案外、TweetsGetterBySearch クラスをばっさり削除すると動くかもしれません。

      • 管理人様
        早速のお返事感謝致します。

        エラーの意味からわからなかったのですが、
        管理人様のおかげで理解出来ました。

        ただ修正すべきところが明確にはわかっていません。
        頑張って修正をかけていきたいと思います。
        また、TweetsGetterBySearchクラスををばっさりいったのも試してみます。

        毎度質問にお答えいただき本当に感謝しています。
        有難うございます。今後また質問するかもしれません。
        どうかその時もよろしくお願い致します。

  20. 管理人様 はじめまして。
    いきなりで申し訳ないのですが一つ質問があります。
    ”沖縄旅行”のサンプルコードを参考にさせていただいたのですが、until sinceなどを用いて日付け指定をしたい場合はどこに挿入すればよいのか、教えていただきたいです。

    • ari さん、こんにちわ

      until は params に追加すれば指定できると思います。

      params = {'q':u'沖縄旅行', 'count':10, 'until':'2018-06-24'}
      (試してないので確実ではありませんが)

      since は残念ながら API で指定できないようです。

      下記のサイトにAPIで使用可能なパラメータが載っています。
      ttps://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets

      ツイートの created_at に日付が入っているので、それを取りだして since until を判定してもいいかもしれません。

  21. 潜水艇金槌 says:

    管理人さま

    こんにちは。
    以前質問させていただきました潜水艇金槌です。
    その節は,ご丁寧にご回答下さりありがとうございました。

    その後,RestAPIを用いてtweetを収集するべく,再び
    貴サイトを参考にさせていただいております。
    スクリプトに手を加えながらいろいろと実行しているのですが,
    1点ご教示いただけませんか?

    retweetも含めて収集したい場合は,
    以下二か所の【False】を【True】に換えて実行すればよいのでしょうか…?
      def collect(self, total = -1, onlyText = False, includeRetweet = False):
      if (('retweeted_status' in tweet) and (includeRetweet is False)):

    素人質問で恐縮なのですが,
    お時間おありの際にご指導いただけますと幸いです。

    • 潜水艇金槌 さん、こんにちわ

      それでも動くのですが、通常は collectメソッド側ではなく呼び出し側を修正します。

      includeRetweet = True を下記のように追加してください。

      getter.collect(total = 3000, includeRetweet = True)

      • 潜水艇金槌 says:

        管理人さま

        こんにちは。
        お忙しい中にもかかわらず,
        ご丁寧にご回答下さりありがとうございます。

        ご教示いただいたように修正し,実行しましたところ,
        無事,RTも取得することができました。
        ありがとうございます。

        また不明点が出てきましたら,
        お手数おかけして申し訳ありませんが
        ご教示いただけますと幸いです。

  22. 管理人様

    こんばんは。
    python学習の参考としてサイトを利用させていただいております。

    retweeted_statusをMongoDBに保存しようと、
    for tweet in tweets:
    tweet2 = {}
    tweet2['retweeted_status'] = tweet['retweeted_status']
    db.xxxxxx.insert(tweet2)
    としましたが、keyerror:retweeted_statusとなりうまくいきません。

    ご教授いただけると幸いです。

  23. 追記
    retweeted_statusは、リツイートのみにしか付加されないので保存時にtweetをそのままinsertしました。
    しかし、retweeted_statusだけ取り出そうとprint(record['retweeted_status'])としてもやはりKeyErrorが出てしまいます。

      • 管理人様
        お忙しいところ、返信感謝いたします。
        print['record']をして、retweeted_statusの存在が確認できている場合でも、KeyErrorと出てしまいます。
        twitter開発者ドキュメントをみても、retweeted_statusが何かの入れ子になっているわけではなさそうなので、なぜキーが存在しないか不明でした。

  24. 管理人様
    こちらのコードを参考に、Twitterデータ取得をさせていただいているpython初学者です。
    いつも、大変お世話になっております。

    1ヶ月ほど前までは正常に作動していたのですが、
    —————————————————————————
    gaierror Traceback (most recent call last)
    ~/.pyenv/versions/anaconda3-5.2.0/lib/python3.6/site-packages/urllib3/connection.py in _new_conn(self)
    140 conn = connection.create_connection(
    –> 141 (self.host, self.port), self.timeout, **extra_kw)
    142

    ~/.pyenv/versions/anaconda3-5.2.0/lib/python3.6/site-packages/urllib3/util/connection.py in create_connection(address, timeout, source_address, socket_options)
    59
    —> 60 for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
    61 af, socktype, proto, canonname, sa = res

    ~/.pyenv/versions/anaconda3-5.2.0/lib/python3.6/socket.py in getaddrinfo(host, port, family, type, proto, flags)
    744 addrlist = []
    –> 745 for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
    746 af, socktype, proto, canonname, sa = res

    gaierror: [Errno -2] Name or service not known

    というエラーが出てしまって、データ取得が出来ないです・・・。

    こちら、管理人様のコードに問題というよりは、私のローカル環境の問題でしょうか・・・?
    自分でも調べてみたのですが、プログラミング初心者のせいか、解決策が分かっていません。

    もしご助言いただければ幸いです。

    • K.Kさん、こんにちは

      はっきりとは判りませんが、socket関連でエラーになっているので、通信環境に問題があるのだと推測します。
      twitterのサーバーが見えていない状態だと思います。

      • 管理人様、ご返信くださりありがとうございます。

        リモートサーバにSSH接続した状態でデータ取得しようとしたところ上記のエラーになり、個人のローカルでデータ取得をしたところ問題なく取得が出来ました。
        原因はまだ特定できていないのですが、とりあえずは取得できています。

  25. 管理人様
    日頃からこちらのコードを参考にさせていただいて、大変お世話になっております。

    totalに大きな値(例えば50000)を指定して実行したところ、今月分のツイートは取得できるのですが、月をまたいでツイートの取得ができませんでした(今月分のツイートを取得し終わると、totalで指定した数に達していなくてもプログラムが終了してしまう)。また、sinceやuntilといった検索方法も試しましたが、先月から前のツイートの取得ができませんでした。

    質問なのですが、先月から前のツイートの取得は可能なのでしょうか?

    お手数おかけして申し訳ありませんが、
    ご助言いただけたら幸いです。

    • R.Kさん、こんにちは

      ツイートは1週間ぶんしか取得できないようです。

      ttps://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets

      の until の説明欄で確認してみてください

  26. 管理人様
    初めまして、こちらのコードを重宝させていただいている者です。

    回数制限に達した後、休止状態を経て、再度ツイートの収集を再開するタイミングで

    ConnectionError: ('Connection aborted.', OSError("(10060, 'WSAETIMEDOUT')"))

    というエラーが出ます。
    解決方法に全く不明なのですが、何かご存じでしょうか。
    お忙しいところ、全くの素人質問で申し訳ありませんが、よろしくお願いいたします、

  27. 管理人様
    Twitterデータ取得でこちらのコードを参考にさせていただいております。

    画像つきのツイートの取得方法はキーワードの後ろにfilter:mediaをつけることで取得できるのですが、画像をダウンロードして保存する方法を教えていただけないでしょうか。

    お手数おかけして申し訳ありませんが、
    ご助言いただけたら幸いです。

  28. 管理人様
    上記のコードを実行すると、tweetの全文を取得できないことがあるのですが、全文を取得するためにはどうすればよろしいでしょうか?
    paramsにtweet_mode=extendedを追加してもうまくいきません。

    お手数ですが、ご助言いただけたら幸いです。
    よろしくお願いいたします。

    • 管理人様
      すみません。解決しました。
      tweet_mode=extendedにすることで、full_textがkeyになっているので、textをfull_textにすればいい話でした。。。

  29. 機械学習に十分な大量のツイートを取得するのに詰まっていたとき、こちらの記事に出会って解決することができました。
    当時は時間がなくきちんとコードの中身を消化せずコピペしてしまったのですが、今は学習用に参考にさせて頂いています。
    即座に実行できるコードだけでなく、丁寧な解説が記載されているので、実用と学習の両方のニーズを満たす素晴らしい記事です。

    ありがとうございます

  30. 時系列全てが動くコードに感謝 says:

    管理人さん
    理解の時系列において、全てが動くコードを掲載いただき、大変感謝いたします。
    他の方もコメントしておられますが、
    プログラムの技術と、他人に教える技術はそれぞれ別物で、両方お持ちの方は大変少ないです。
    (私見です。お気を悪くされる方がおられたら申し訳ございません。)
    プログラムの羅列ではなく、教える文章の記載は大変かとは思いますが、
    今のスタイルを続けていただけると、学習者として大変ありがたいです。
    また、各種コメントに対する姿勢も只々称賛しています。

    ありがとうございます

  31. 管理人様
    初めまして。こちらのコードを参考にtwitterのデータ収集を行っているpython初心者です。

    コードを実行した際に、恐らくですが絵文字が原因でエラーが出てしまいます。
    ツイート本文から絵文字を消去してテキスト化するにはどうすれば良いでしょうか。

    素人質問ですが、ご助言いただけたら幸いです。

  32. 管理人様
    ありがとうございます。
    大量取得しようとして取得制限でつまずいていたところ、このドキュメントに行きつきました。
    やりたかったことまで行けそうです!

  33. 管理人様
    はじめまして。わかりやすい記事ありがとうございます。
    該当ユーザーのツイート(おそらく1100件)をTwitter開始日から全て取得したいのですが、開始日から2ヶ月半くらいがなぜか取得できません。
    ユーザーが絵文字やハッシュタグを多用しているからなのでしょうか?よろしくお願いします。

  34. 上記追記です。
    2018-10-13〜2020-11-30までのツイートは取れるのですが、それ以前2ヶ月半のツイートが取得できない、と言う意味です。

  35. Twitter API NIGATE says:

    管理人様
    はじめまして。
    大学の研究で、ツイートを利用したいと考えていたところ、この記事にたどり着きました。
    本当にわかりやすく、とても助かりました。この記事のおかげで、一週間のツイートを取得することができました。ありがたく存じます。
    ここで質問なのですが、自分は一週間以上前のツイートを取得するために普通のkeyだけではなく、(公式の?)keyと、Project申請まで行い、それに対応するAccess Tokenなど4つのkeyを取得したのですが、これを差し替えるだけでは一週間以上前のツイートを取得することができません。
    specifyUrlAndParamsメソッド下のurl を'https://api.twitter.com/1.1/search/tweets.json' から  'https://api.twitter.com/1.1/tweets/search/fullarchive/dev/counts.json'に差し替えたのですが、API403エラーが出てしまいます。
    他にどこを直すべきでしょうか。ご指摘いただけると、幸いです。知識不足で申し訳ありません。宜しくお願い致します。

  36. 管理人様

    2021年4月25日現在、上記コードをColaboratory上で実行したところ、ほぼ完璧に動作しています。
    しかし、totalを3000件やそれ以上に設定しても、およそ2400~2700件でスクレイピングが停止してしまいます。

    何が原因だと考えれられるでしょうか?

  37. 管理人様

    上記のコードを元に、日時の範囲を指定してスクレイピングするにはどうすれば良いでしょうか?

SUSUMU へ返信する コメントをキャンセル