Cookieで何が出来るのか【Twitterでフォロワーの誕生日一覧を取得する】

プログラミング
two 3d humans give their hand for handshake
この記事は約9分で読めます。

アンケートにこのような質問があったので回答してみたいと思います。

twitterのcookieについてもっと深掘りした記事がみてみたいです

Cookieとは

すごく簡単に説明するとCookieとはサーバ上から送られてきた認証情報などを保存しているものです。

Cookieは「その人自身」を示すものであり、Cookieを利用すれば「その人自身」としてAPIを実行することが出来るものです。

ブラウザから何か操作を行うとサービスを提供しているサーバにCookieを含めて情報を送ります。

重要なのは

TwitterBotなどで認証した情報でなく、ブラウザでログインした本人そのもの

であることです。

Twitterで提供しているAPIは様々ありますが、それはBotが利用できるAPIであり、Twitterを動かすために使われている全てのAPIを利用できるわけではありません。

アカウントを削除したり、パスワードを変えたり、通常Botでやられては困ることもCookieがあればブラウザで実行したように操作することが出来ます(※理論上は)

そのためCookieは絶対に外部に漏らしてはいけない情報という認識でいてください。

今回は通常Botでは取得できないアカウントの誕生日の情報をCookieを使って一覧取得する方法を紹介したいと思います。

Twitterの誕生日一覧を取得する方法

方法は以下の手順を踏んでもらえればOKです

  1. Twitterのサイトに移動します
  2. ブラウザでデベロッパーツールを開きます(※MacのChromeは動作確認済み)
  3. consoleタブを開きます
  4. 一番下の『>』の部分に文字を入力出来るようになっているので、以下のコマンドをコピペして実行します
let ct0="";let twid="";let count=0;const birthdayKey="completeBirthdayKey";let birthdayList=[];const completeUserNames=[];function main(){init();let cursor=-1;const a=function(g){const d=JSON.parse(g.target.responseText);prevCursor=cursor;cursor=d.next_cursor_str;const c=d.users;const b=c.length;if(b===0){console.log("finish");localStorage.removeItem(birthdayKey);output();return}const f=function(m){if(xhr.status===200){const h=JSON.parse(m.target.responseText);const k=h.data.user.legacy_extended_profile;const j=k.birthdate;let year="";let month="";let day="";if(typeof j!=="undefined"){year=j.year;month=j.month;day=j.day}const l=c[count];let log=l.name+" : ";if(year){log+=year+"年"}if(month){log+=month+"月"}if(day){log+=month+"日"}if(year===""&&month===""&&day===""){log+="未設定"}console.log(log);birthdayList.push([l.name,year,month,day,"https://twitter.com/"+l.screen_name]);count++;if(b===count){if(cursor===0){console.log("finish");localStorage.removeItem(birthdayKey);output()}else{count=0;_getFollowUsers(cursor,a)}}else{_getProfile(c[count].screen_name,f)}}else{if(xhr.status===429){localStorage.setItem(birthdayKey,JSON.stringify(birthdayList));console.warn("実行回数の限度に達しました。15分後にページを更新して再度実行してください。")}}};while(c.length>count&&completeUserNames.indexOf(c[count].screen_name)!==-1){count++}_getProfile(c[count].screen_name,f)};_getFollowUsers(cursor,a)}function _getFollowUsers(c,d){const b="count=200&cursor="+c+"&user_id="+twid;const a="https://api.twitter.com/1.1/friends/list.json?"+b;fetch(a,null,"GET",d)}function _getProfile(a,b){let url="https://twitter.com/i/api/graphql/Vf8si2dfZ1zmah8ePYPjDQ/UserByScreenNameWithoutResults?variables=%7B%22screen_name%22%3A%22"+a+"%22%2C%22withHighlightedLabel%22%3Atrue%7D";fetch(url,null,"GET",b)}function fetch(a,b,d,c){xhr=new XMLHttpRequest();xhr.open(d,a);xhr.setRequestHeader("content-type","application/x-www-form-urlencoded;charset=UTF-8");xhr.setRequestHeader("Authorization","Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA");xhr.setRequestHeader("x-csrf-token",ct0);xhr.onload=c;xhr.send(b)}function init(){const b=document.cookie.split(";");for(let i in b){const e=b[i];if(e.indexOf("ct0")!==-1){const c=e.split("=");ct0=c[1]}if(e.indexOf("twid")!==-1){const f=e.split("=u%3D");twid=f[1]}}const d=localStorage.getItem(birthdayKey);let list=JSON.parse(d);if(list===null){list=[]}birthdayList=list;for(let i in birthdayList){const a=birthdayList[i][4].replace("https://twitter.com/","");completeUserNames.push(a)}}function output(){let data="";for(let i in birthdayList){const c=birthdayList[i];for(let i in c){if(c[i]){data+=c[i]+"\t"}else{data+="\t"}}data+="\r\n"}const b=new Uint8Array([239,187,191]);const a=new Blob([b,data],{type:"text/tab-separated-values"});console.warn("birthday.tsv をダウンロードします。");const d=document.createElement("a");d.setAttribute("download","birthday.tsv");d.setAttribute("onclick","handleDownload()");d.setAttribute("href",window.URL.createObjectURL(a));d.click()}main();

全員分誕生日を取得すると birthday.tsv というファイルを自動でダウンロードします。

ちょっとした解説

デベロッパーツールは開いたそのページに対して情報を出すツールです。

consoleページはそのページ上でJavaScriptを実行することが出来るのですが、その中でHTTPリクエストを送ると「そのページからリクエストを送ったようにデータを送信する」ことが出来ます。

つまり、その際にブラウザに保存されているCookieデータも一緒に送っています。

今回の誕生日を取得するプログラムは、プロフィールページにアクセスした時に利用する通常公開されていない誕生日を取得するAPIをプログラムから大量に実行します。

同じAPIをTwitterBotから叩こうとしても権限がなく弾かれますが、デベロッパーツール上からの実行だとその人自身という判定になるので実行できてしまうというわけです。

実行後はLocalStorageという場所に結果を保存していき終わったら tsv に書き出す処理を行います。

15分900回までの上限があるので、もしフォロー数が多い人は何回かに分けて実行してください。

最後に

このようにCookieについての基礎とデベロッパーツールの挙動を知っておくと、Twitterに限らず様々なサイトで人間が手動で行う操作をプログラムでまとめて実行できてしまうことがわかります。

今回のコードは誕生日一覧を表示するだけの無害なプログラムですが、ビジネス利用することも悪用することも出来てしまいます。

当ブログで何度か行っているTwitterBotの作り方とは違い、基本リクエストを受けて無料で記事を作成することは予定していません。(有料でいいなら考える…(。・_・。))

先程のコードを読んで大体理解できた人は自己責任で様々なプログラムを書いてみてください〜

ここまで読んで頂きありがとうございました!

よろしければ↓からサポートお願いいたします!

コメント

タイトルとURLをコピーしました