Help us understand the problem. What is going on with this article?

[Python] OAuth認証でTwitter連携/ログインを実装する

More than 1 year has passed since last update.

:star: 概要

  • PythonでTwitter連携を実装しようとしてみたところ、あんまり例がなかったのでつくってみました
  • ドキュメントを読めば分かるという人はこちら → Implementing Sign in with Twitter
  • ざっくりいうと、こういうやつのこと example

:star: 流れ

  • Twitterのアプリを作成する
  • リクエストトークンを取得して連携画面のURLを生成する
  • 連携後のパラメーターを使ってアクセストークンを生成する
  • アクセストークンを使ってユーザーのツイートを取得する

:pencil2: Twitterのアプリを作成する

  • Twitter Application Management の右上の"Create New App"からアプリを作成します
  • Name, Descripiton, Website は適宜入力してください(認証画面に表示される内容です)
  • CallbackURLsに連携ボタンを押した後に遷移するURLを設定する必要があります(Twitter連携を実装する場合は必須)
  • このCallbackURLsは前方一致ではなく完全一致でないといけなくなりました(2018/06頃より)
  • アプリ作成後、次の画面でConsumerKeyとConsumerSecretを確認できます

apps.twitter.com_app_15226818_keys(Laptop with MDPI screen).png

:pencil2: リクエストトークンを取得して連携画面のURLを生成する

  • 連携画面のURLはhttps://api.twitter.com/oauth/authenticate?oauth_token=XXXのようになっています
  • このXXXに入るのがリクエストトークンと呼ばれるものです
  • リクエストトークンは POST oauth/request_token より取得できます
  • 先ほど設定したCallbackURLsのうち、どれかをoauth_callbackとしてパラメーターに渡す必要があります
  • OAuthセッションを1から作るのは面倒ですが、requests_oauthlibというライブラリを使うことで簡単に実装できます
    from requests_oauthlib import OAuth1Session
    from urllib.parse import parse_qsl

    consumer_key = "Consumer Key を入力"
    consumer_secret = "Consumer Secret を入力"

    # Twitter Application Management で設定したコールバックURLsのどれか
    oauth_callback = "CallbackURLsのどれか"

    twitter = OAuth1Session(consumer_key, consumer_secret)

    response = twitter.post(
        request_token_url,
        params={'oauth_callback': oauth_callback}
    )

    # responseからリクエストトークンを取り出す
    request_token = dict(parse_qsl(response.content.decode("utf-8")))

    # リクエストトークンから連携画面のURLを生成
    authenticate_url = "https://api.twitter.com/oauth/authenticate"
    authenticate_endpoint = '%s?oauth_token=%s' \
        % (authenticate_url, request_token['oauth_token'])

    print(authenticate_endpoint)

:pencil2: 連携後のパラメーターを使ってアクセストークンを生成する

  • 先ほど生成したURLにアクセスして「連携アプリを認証」すると、指定したcallbackURLに遷移します。この時、URLには?oauth_token=YYY&oauth_verifier=ZZZというパラメーターがついているはずです
  • この2種類のパラメーターを使うことで、アクセストークンを生成し、連携したユーザーとしてTwitterのAPIを叩くことができるようになります
  • アクセストークンは POST oauth/access_token より取得することができます
  • アクセストークンにはoauth_tokenoauth_token_secretの2つが含まれており、両方とも必要です
    from requests_oauthlib import OAuth1Session
    from urllib.parse import parse_qsl

    consumer_key = "Consumer Key を入力"
    consumer_secret = "Consumer Secret を入力"

    oauth_token = "callbackURLのパラメーター(YYY)"
    oauth_verifier = "callbackURLのパラメーター(ZZZ)"

    twitter = OAuth1Session(
        consumer_key,
        consumer_secret,
        oauth_token,
        oauth_verifier,
    )

    response = twitter.post(
        access_token_url,
        params={'oauth_verifier': oauth_verifier}
    )

    # responseからアクセストークンを取り出す
    access_token = dict(parse_qsl(response.content.decode("utf-8")))

    print(access_token)

:pencil2: アクセストークンを使ってユーザーのツイートを取得する

  • 上記で取得したアクセストークンを使ってユーザーのツイートを取得する例です
  • GET statuses/user_timeline より取得することができます
    import json

    consumer_key = "Consumer Key を入力"
    consumer_secret = "Consumer Secret を入力"

    access_token = {
        'oauth_token': "アクセストークンの中のoauth_token",
        'oauth_token_secret': "アクセストークンの中のoauth_token_secret",
    }

    params = {
        'user_id': "アクセストークンの中のuser_id",
        'exclude_replies': True,
        'include_rts': json.get('include_rts', False),
        'count': 20,
        'trim_user': False,
        'tweet_mode': 'extended',    # full_textを取得するために必要
    }

    twitter = OAuth1Session(
        consumer_key,
        consumer_secret,
        access_token['oauth_token'],
        access_token['oauth_token_secret'],
    )

    response = twitter.get(user_timeline_url, params=params)
    results = json.loads(response.text)

    print(results)

:pencil: flaskでAPIとして実装した例

index.py

import os
import json
from urllib.parse import parse_qsl

from flask import Flask, jsonify, request
from requests_oauthlib import OAuth1Session

app = Flask(__name__)


consumer_key = "Consumer Key を入力"
consumer_secret = "Consumer Secret を入力"


base_url = 'https://api.twitter.com/'

request_token_url = base_url + 'oauth/request_token'
authenticate_url = base_url + 'oauth/authenticate'
access_token_url = base_url + 'oauth/access_token'

base_json_url = 'https://api.twitter.com/1.1/%s.json'
user_timeline_url = base_json_url % ('statuses/user_timeline')


# 認証画面(「このアプリと連携しますか?」の画面)のURLを返すAPI
@app.route('/twitter/request_token', methods=['GET'])
def get_twitter_request_token():

    # Twitter Application Management で設定したコールバックURLsのどれか
    oauth_callback = request.args.get('oauth_callback')

    twitter = OAuth1Session(consumer_key, consumer_secret)

    response = twitter.post(
        request_token_url,
        params={'oauth_callback': oauth_callback}
    )

    request_token = dict(parse_qsl(response.content.decode("utf-8")))

    # リクエストトークンから認証画面のURLを生成
    authenticate_endpoint = '%s?oauth_token=%s' \
        % (authenticate_url, request_token['oauth_token'])

    request_token.update({'authenticate_endpoint': authenticate_endpoint})

    return jsonify(request_token)


# アクセストークン(連携したユーザーとしてTwitterのAPIを叩くためのトークン)を返すAPI
@app.route('/twitter/access_token', methods=['GET'])
def get_twitter_access_token():

    oauth_token = request.args.get('oauth_token')
    oauth_verifier = request.args.get('oauth_verifier')

    twitter = OAuth1Session(
        consumer_key,
        consumer_secret,
        oauth_token,
        oauth_verifier,
    )

    response = twitter.post(
        access_token_url,
        params={'oauth_verifier': oauth_verifier}
    )

    access_token = dict(parse_qsl(response.content.decode("utf-8")))

    return jsonify(access_token)



@app.route('/twitter/user_timeline', methods=['GET'])
def get_twitter_user_timeline():

    access_token = request.args.get('access_token')

    params = {
        'user_id': request.args.get('user_id'),
        'exclude_replies': True,
        'include_rts': json.get('include_rts', False),
        'count': 20,
        'trim_user': False,
        'tweet_mode': 'extended',    # full_textを取得するために必要
    }

    twitter = OAuth1Session(
        consumer_key,
        consumer_secret,
        access_token['oauth_token'],
        access_token['oauth_token_secret'],
    )

    response = twitter.get(user_timeline_url, params=params)
    results = json.loads(response.text)

    return jsonify(results)

if __name__ == "__main__":
    port = os.environ.get('PORT', 3333)
    app.run(
        host='0.0.0.0',
        port=port,
    )

:star: 感想

  • OAuth認証の流れやお作法的なものがあんまり分かっていなかったので思ったより苦戦しました
  • CallbackURLについてはフロントの話なので省きましたが、前方一致ではなく完全一致なのでhttps:///example.com/user/001/twitterのような構成だったので少し工夫が必要でした
  • Facebook/Instagramの認証もPython+React.jsで実装したので、そのうち記事を書こうと思います

:star2: 追記

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away