タイトルはネタであり、このあとに書く文章も適当な文章です。
まえがき
昔々、フォロー返しという文化がありました。Twitterで誰かをフォローするとお返しにフォロー返しをするというやつです。
その文化を利用してたくさんのアカウントがフォロワー数を増やし始めました。
勿論全てのアカウントがフォロー返しをしてくれるわけではありません。
フォロー返しをしてくれないアカウントをそのままにフォローし続けると、自分のアカウントのフォローとフォロワーの数の関係性が以下のようになってしまいます。
フォロー数 5000 / フォロワー数 2500
これではいけません。
なぜなら周りからはフォロー返しの文化を利用してアカウントのフォロワー数を増やそうとしていることがバレバレだからです。
さて、フォロー返しをしてくれないアカウントは フォロー返し文化を利用してフォロワー数を増やす
という目的から見ると、完全に不要なアカウントとなります。
そういうアカウントはフォローを解除しないといけませんね。
さて、フォロー返しをしてくれないアカウント、というのはアカウントのフォロー画面から確認が可能です。 ですが、数千ものアカウントをフォローしている場合、これらをいちいち確認するのは面倒です。
退屈なことをはプログラムにやらせよう的な本があります。Pythonの本ですね。
(ちなみにこの本、今年の11月に第2版が出るそうです)
我々もフォロー返ししてくれないアカウントをプログラムを使って特定しましょう。
今回、言語はJavaScript(Node.js)を用います
Twitter API v2を使ってフォロー返ししてくれないアカウントを特定する
さて、本題です。
の前に、今回の内容、ならびに実行する環境について説明していきます。
Essentialプランを利用
まずTwitter API v2はEssentialプランを想定しています。
Essentialプランは登録が楽ですが、すぐに制限に到達してしまいます。
本当にすぐで、私が開発している最中にテストで動かしてみただけで制限に到達してしまうぐらいの天井の低さです。
※Essentialプランの登録については下記にも書いているのでよろしければ見てみてください。
本当は無料でもっと天井が高いプランもあるのですが、Twitterに申請用の文章(しかも英語)を書いて送るようなことをしなくてはなりません。
とっても面倒ですよね。楽したくてTwitter APIを使うのに英語の作文を考えるだけで疲れてしまうので、楽に作れるEssentialプランにしましょう。
もしあなたのアカウントのフォロー・フォロワー数が多い場合、制限に引っかかる可能性もあります。
その場合はスリープを挟んで上手く制限に引っかからないように感覚を空けてやりましょう。
この方法だと時間はかかってしまいますが、そもそも実行中はPCの前にいる必要もないので、コーヒータイムしたりApex Legendsで遊んでいたりすればよいのです。
ちなみにフォロワーなどのアカウントを取得するAPIの制限が具体的にどれぐらいなのかは、下記のドキュメントを見る限りはわかりませんでした。
(何れにせよ天井は低いです)
フォロー返ししてくれないアカウントを特定していく
というわけで本題です。
今回の流れとしては、
- フォローしているアカウントのリストを取得する
- フォローされているアカウントリストを取得する
- 上2つのリストを照らし合わせてフォロー返ししてくれていないアカウントを特定する
という非常に原始的な方法でフォロー返ししてくれないアカウントの数を特定していこうと思います。
これらの操作を一連のプログラムとして一度にやってもよいのですが、前述の通り、APIの制限に引っかかるので、一つ一つ実行していくという形でやっていきます。
フォローしているアカウントのリストを取得する
まずはコードを貼ります。
import { Client } from "twitter-api-sdk"; import { createObjectCsvWriter } from "csv-writer"; const sleep = msec => new Promise(resolve => setTimeout(resolve, msec)); const FOLLOWING_LIST_CSV_PATH = "following-list.csv"; const CSV_HEADER = [ {id: "id", title: "id"}, {id: "name", title: "name"}, {id: "username", title: "username"}, {id: "url", title: "url"}, {id: "description", title: "description"}, ]; const twitterParams = { max_results: 1000, "user.fields": ["id", "name", "username", "url", "description"] } const getUserId = async (client, userName) => { const { data } = await client.users.findUserByUsername(userName); return data.id; } const createFollowingList = async(userId, params) => { const followingListWriter = createObjectCsvWriter({ path: FOLLOWING_LIST_CSV_PATH, header: CSV_HEADER }) const followings = client.users.usersIdFollowing(userId, params); for await (const page of followings) { console.log(page.data); await followingListWriter.writeRecords(page.data); console.log('fetch following list...') await sleep(1000); } } // main const client = new Client(process.env.BEARER_TOKEN); const userName = "自分のアカウント名(@から始まるやつ)を入れてください"; const userId = await getUserId(client, userName); await createFollowingList(userId, twitterParams);
このコードをコピペして、followingList.mjs
というファイルに貼り付け、下記の要領で実行します。
BEARER_TOKEN=<取得したtoken> node followingList.mjs
すると、あなたのフォローしているアカウントのリストが following-list.csv
というファイルに集計されていきます。
もしアカウントのフォロー数が多い場合、制限に到達してしまいます。
その場合は、 await sleep(1000);
となっている箇所を await sleep(60000);
などとして1分おきにリストを取得するようにすることで制限に到達しないでリストを取得し続けることが可能かもしれません。
これについては未検証なのですが、twitterのEssentialプランの内容的にこれぐらいなら大丈夫そうかなという、かなりアバウトなノリで書いていますのでその点ご了承ください。
言うまでもなく時間はとてもかかるので、その間は別のことをしておくのがおすすめです。
フォローされているアカウントリストを取得する
次は同じ要領で自身をフォローしてくれているフォロワーのリストを取得します。
import { Client } from "twitter-api-sdk"; import { createObjectCsvWriter } from "csv-writer"; const FOLLOWER_LIST_CSV_PATH = "follower-list.csv"; const sleep = msec => new Promise(resolve => setTimeout(resolve, msec)); const CSV_HEADER = [ {id: "id", title: "id"}, {id: "name", title: "name"}, {id: "username", title: "username"}, {id: "url", title: "url"}, {id: "description", title: "description"}, ]; const twitterParams = { max_results: 1000, "user.fields": ["id", "name", "username", "url", "description"] } const getUserId = async (client, userName) => { const { data } = await client.users.findUserByUsername(userName); return data.id; } const createFollowersList = async(userId, params) => { const followerListWriter = createObjectCsvWriter({ path: FOLLOWER_LIST_CSV_PATH, header: CSV_HEADER }) const follows = client.users.usersIdFollowers(userId, params); for await (const page of follows) { console.log(page.data); await followerListWriter.writeRecords(page.data); console.log('fetch follower list...') await sleep(1000); } } // main const client = new Client(process.env.BEARER_TOKEN); const userName = "自分のアカウント名(@から始まるやつ)を入れてください"; const userId = await getUserId(client, userName); await createFollowersList(userId, twitterParams);
このコードをコピペして、followerList.mjs
というファイルに貼り付け、下記の要領で実行します。
BEARER_TOKEN=<取得したtoken> node followerList.mjs
すると、今度はあなたのフォロワーのリストが follower-list.csv
というファイルに集計されていきます。
フォロワー数が多くて制限に到達するケースは、上に書いたのと同じなので割愛します。
リストを照らし合わせてフォロー返ししてくれていないアカウントを特定する
これでフォローとフォロワーのリストをCSV形式で作成することができました。
今度はこの2つのリストを照らし合わせて、フォローしているけど私のことをフォローしてくれていないアカウントを特定していきます。
コードは以下です。
import { createObjectCsvWriter } from "csv-writer"; import { parse } from "csv-parse/sync"; import { existsSync, readFileSync } from "node:fs"; const FOLLOWING_LIST_CSV_PATH = "following-list.csv"; const FOLLOWER_LIST_CSV_PATH = "follower-list.csv"; const UNFOLLOW_USER_LIST_CSV_PATH = "unfollow-user-list.csv"; const CSV_HEADER = [ { id: "id", title: "id" }, { id: "name", title: "name" }, { id: "username", title: "username" }, { id: "url", title: "url" }, { id: "description", title: "description" }, ]; const getUnfollowUserList = async () => { if ( !existsSync(FOLLOWER_LIST_CSV_PATH) || !existsSync(FOLLOWING_LIST_CSV_PATH) ) { throw new Error( `Not found csv file(${FOLLOWER_LIST_CSV_PATH} or ${FOLLOWING_LIST_CSV_PATH})`, ); } const followerCsvData = readFileSync(FOLLOWER_LIST_CSV_PATH, "utf8"); const followerRecords = parse(followerCsvData, { columns: true }); const followerIdList = followerRecords.map(({ id }) => id); const followingCsvData = readFileSync(FOLLOWING_LIST_CSV_PATH, "utf8"); const followingRecords = parse(followingCsvData, { columns: true }); const unfollowUserList = followingRecords.filter(({ id }) => !followerIdList.includes(id) ); const unfollowUserListWriter = createObjectCsvWriter({ path: UNFOLLOW_USER_LIST_CSV_PATH, header: CSV_HEADER, }); await unfollowUserListWriter.writeRecords(unfollowUserList); return; }; // main await getUnfollowUserList();
このコードを notFollowerList.mjs
にコピペして実行しましょう。
(ちなみに今更ですが、かなりコードは雑です。どこかで整理してGitHubにあげようかと思っています)
なお今度の処理はTwitter APIは使わないため、今までとは違い実行時に BEARER_TOKEN
の指定は不要です。
このコードを実行すると、unfollow-user-list.csv
というファイルが作られます。
そこにはフォローしているけどフォローはされていないアカウントのリストが表示されています。
これで準備はバッチリです。あとは手作業でフォロー返ししてくれていないアカウントのフォローを外していきましょう。
アンフォローもTwitter APIで行えばいいのでは?
おっしゃるとおり twitter-api-sdk
内にもアンフォローに関する関数は用意されていました。
が今はどうかわかりませんが、以前は1日内に特定の数以上のアカウントをアンフォローしているとバンされる、という噂がありました。
現状TwitterのAPIに対するリクエストの制限を見ていても、おそらくアンフォローを一度大量に行うと制限が入る、またはアカウント凍結のリスクもあるかもしれません。
危険な橋は渡らないに越したことはないため、アンフォロー処理は手作業で、と書きました。
TODO
上に書いたコードを整理してそのうちGitHubにあげようと思っています。
上げたらこちらに追記します。