Open2

Twitter Mobile の GraphQL APIのメモ

okuokuokuoku

Twitterのアーカイブをリクエスト( https://twitter.com/okuoku/status/1644011517531258880 )したらめっちゃ品質の良いアーカイブが来てちょっと不味いものを感じたので。。

今回は1日とかで来たけど、twilog亡き今、真面目な検索手法としてコレじつは有望なんではないか。。ただ1GiBとかの転送が各ユーザに掛かる(全mediaとか消したtweet等が含まれる)ので、あんまり酷使するとTwitterが破産しちゃうと思う。

okuokuokuoku

Guest Token(gt) および APIマッピングの取得

Guest Token

非ログイン状態で https://mobile.twitter.com/okuoku のようにユーザ名のページにアクセスすると、Cookieとして払い出される。

Guest Tokenがどのようにexpireするのかは不明。

Bearer Token

これは main に含まれている。今回は https://abs.twimg.com/responsive-web/client-web-legacy/main.686f535a.js だった。

... Twitterは長年このtokenを使いまわしており、検索すると大量の使用例がみつかる。

APIマッピング

Twitter mobileはWebPackされたPWAアプリなので、分割先のスクリプトの取得が必要。

今回は、 https://abs.twimg.com/responsive-web/client-web/api.1104a7aa.js だった。これの中身は

window.webpackChunk_twitter_responsive_web.filter(e => e[0][0] == "api")
let temp = window.webpackChunk_twitter_responsive_web.filter(e => e[0][0] == "api")[0]
let temp2 = {}
let ops = {}
Object.keys(temp[1]).forEach(k => {temp2[k] = {}; try {temp[1][k](temp2[k])} catch(e){}})
Object.keys(temp2).forEach(k => {if(temp2[k].exports && temp2[k].exports.queryId){ops[temp2[k].exports.operationName] = temp2[k].exports}})

のようにして、動作中のDOMから ops に抽出できる。今回の場合、必要なのは UserTweetsAndReplies なので、 ops.UserTweetsAndReplies の内容:

{
    "queryId": "_dEwIMW2hHUTejaIafUiLA",
    "operationName": "UserTweetsAndReplies",
    "operationType": "query",
    "metadata": {
        "featureSwitches": ["blue_business_profile_image_shape_enabled",
            "responsive_web_graphql_exclude_directive_enabled",
            "verified_phone_label_enabled",
            "responsive_web_graphql_timeline_navigation_enabled",
            "responsive_web_graphql_skip_user_profile_image_extensions_enabled",
            "tweetypie_unmention_optimization_enabled", "vibe_api_enabled",
            "responsive_web_edit_tweet_api_enabled",
            "graphql_is_translatable_rweb_tweet_is_translatable_enabled",
            "view_counts_everywhere_api_enabled",
            "longform_notetweets_consumption_enabled",
            "tweet_awards_web_tipping_enabled",
            "freedom_of_speech_not_reach_fetch_enabled",
            "standardized_nudges_misinfo",
            "tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled",
            "interactive_text_enabled",
            "responsive_web_text_conversations_enabled",
            "longform_notetweets_richtext_consumption_enabled",
            "responsive_web_enhance_cards_enabled"
        ]
    }
}

が呼出しに必要ということになる。

パラメタとしては更に UserByScreenName の出力も必要で、こちらは、

{
    "queryId": "k26ASEiniqy4eXMdknTSoQ",
    "operationName": "UserByScreenName",
    "operationType": "query",
    "metadata": {
        "featureSwitches": ["blue_business_profile_image_shape_enabled",
            "responsive_web_graphql_exclude_directive_enabled",
            "verified_phone_label_enabled",
            "responsive_web_graphql_skip_user_profile_image_extensions_enabled",
            "responsive_web_graphql_timeline_navigation_enabled"
        ]
    }
}

となっている。これらの内容も現状では固定されているようだ。