Twitterのフォロワー数に意味があるのか？実験してみると意外な結果に

こんにちは。[minmeeting](https://minmeeting.jp/)の伊勢川です。

<a title="minmeeting - 10分で生産的なミーティングができる会議ツール" href="https://minmeeting.jp/" target="_blank"><img width="100px" src="https://qiita-image-store.s3.amazonaws.com/0/199506/32e65577-a5bb-2c3b-4d30-4690c3c5ce0f.png" /></a>

最近よく見かける、<B>Twitterの相互フォロー</B>やリツイート企画。
企業の広告などでも見かけるほど流行ってきていますが、<B>本当に意味があるのでしょうか？</B>

相互フォローとは、フォローしてくれたお礼に相手をフォローすることです。
相互フォローのハッシュタグで検索をして、その人達（bot？）をフォローしていけば、フォローバックされて数だけが増えるという仕組みです。

確かにそれをやればフォロワーは増えるのでしょうが、<B>数だけ増やして何かいいことがあるのでしょうか？</B>
フォロワー数だけを増やすゲームに対して、<B>プラットフォーマーはどう対処しているのでしょうか？</B>

そんなことが気になり、試しに実験してみることにしました。
まずは、その<B>実験結果</B>についてご紹介をして、
後に<B>Twitter APIを用いた相互フォローを自動化するためのコード</B>もご紹介します。

# 当初の仮説
- フォロワーが増えればインプレッションが高まる
- フォロワーを増やしたいだけの人が集まるため、エンゲージメントは下がる
- フォロー＆リツイート企画で、リンクを拡散してもらえば、リンクのアクセス数が増える

これらが<B>当初考えていた仮説</B>でした。
結論から言うと、まあまあ<B>間違っていました</B>。
以下で順次解説します。

# 全体の数字での比較
Twitterのアナリティクスの画面にて、アカウント全体で比較してみましょう。

普段マジメに運用しているアカウント[@a_isegawa](https://twitter.com/a_isegawa)（140 followers）のパフォーマンスはこちら。
<img width="938" alt="スクリーンショット 2019-11-29 20.57.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199506/f1d94644-7913-85a2-4cd9-f0bbea77a90a.png">

相互フォロー実験アカウント[@ise_test](https://twitter.com/ise_test)（1100 followers）のパフォーマンスはこちら。
<img width="950" alt="スクリーンショット 2019-11-29 20.58.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199506/c15a66a4-eeb5-6a36-c2ca-1300cb432546.png">

相互フォローの方がインプレッションも高く、プロフィールのアクセスも高い。
一見すると、相互フォローの方がいいように見えます。
仮説どおりかな？

しかし、細かく見ていくとそうとも言い切れないことが分かりました。

# 同じツイートの同時投稿で実験
では、<B>同じ内容を2つのアカウントにほぼ同時に投稿</B>してみると、どのような結果になるでしょうか。

比較してみると意外なことに、フォロワー数の多い<B>相互フォロー</B>アカウントには、<B>拡散力が非常に弱い</B>ことが分かりました。
普段マジメに運用しているアカウントの方が、フォロワー数が圧倒的に少ないのに、パフォーマンスが高かったのです。

Twitterのタイムライン表示アルゴリズムはよくできていますね。以下、詳細を説明します。

## 本アカウント [@a_isegawa](https://twitter.com/a_isegawa) （140 followers） の投稿
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199506/f359de88-b3a1-5df4-7d63-94b4d2570784.png)

## 相互フォロー実験アカウント [@ise_test](https://twitter.com/ise_test) （1100 followers） の投稿
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199506/3dc3f99a-2466-57b7-3aca-4a239b03322a.png)

## 両者を比較
### インプレッション数の比較
インプレッションの数を比較すると、当初の仮説に反して、<B>フォロワー数の少ないアカウントの方が倍近く</B>伸びています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199506/3e761f3c-c30f-48d0-f0fa-b36298bfa183.png)

### エンゲージメント率の比較
エンゲージメント率を比較すると、こちらは当初の仮説通り、真面目アカウントの方が高いという結果になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199506/b5df2392-373d-0cf1-d1bb-5cabff722521.png)

# リンクの拡散は意味があるか
次にリンクの拡散についての実験です。
下記のように、フォロー＆リツイートしてくれたら、相手をフォロー＆リツイートしますよという投稿を、<B>リツイート企画</B>などと言ったりします。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">会議を変えたい人とつながりたい🙏<br><br>みなさまの固定ツイートをRT＆フォローいたします<br><br>【参加条件】<br>1️⃣このツイートをRT<br>2️⃣フォローは必須<br><br>【期限】<br>11/17 23:59<a href="https://t.co/VLL4XKF0gR">https://t.co/VLL4XKF0gR</a><a href="https://twitter.com/hashtag/%E7%9B%B8%E4%BA%92%E3%83%95%E3%82%A9%E3%83%AD%E3%83%BC?src=hash&amp;ref_src=twsrc%5Etfw">#相互フォロー</a><a href="https://twitter.com/hashtag/%E3%83%95%E3%82%A9%E3%83%AD%E3%83%90?src=hash&amp;ref_src=twsrc%5Etfw">#フォロバ</a><a href="https://twitter.com/hashtag/%E3%83%95%E3%82%A9%E3%83%AD%E3%83%BC%E6%94%AF%E6%8F%B4?src=hash&amp;ref_src=twsrc%5Etfw">#フォロー支援</a><a href="https://twitter.com/hashtag/%E5%9B%BA%E5%AE%9A%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88?src=hash&amp;ref_src=twsrc%5Etfw">#固定ツイート</a><a href="https://twitter.com/hashtag/%E5%9B%BA%E5%AE%9A%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88%E3%83%AA%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88%E8%BF%94%E3%81%97?src=hash&amp;ref_src=twsrc%5Etfw">#固定ツイートリツイート返し</a><a href="https://twitter.com/hashtag/%E3%83%AA%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88%E4%BC%81%E7%94%BB?src=hash&amp;ref_src=twsrc%5Etfw">#リツイート企画</a> <a href="https://t.co/RF4bgqD82j">pic.twitter.com/RF4bgqD82j</a></p>&mdash; フォロワー仙人 (@ise_test) <a href="https://twitter.com/ise_test/status/1194752719497515008?ref_src=twsrc%5Etfw">November 13, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

これをやると、自分のタイムラインがほぼ無意味なリツイートだらけになるため、非常に抵抗がありましたが、拡散効果も大きいため、実験してみることにしました。
とにかくたくさんリツイートされるため、ここにリンクを貼ったら、リンク先に誘導できるかもしれない。
そうすれば、SEO的にも効果があるかと思って、リツイート企画にリンクを貼り付けてみました。

その結果は下記の通り。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199506/a9f8a963-1ba7-b198-6d88-e812feddf00c.png)
インプレッションも、エンゲージメント数も高く、一見うまくいったかのように見えますが、<B>惨敗</B>でした。
<B>リンクのクリック数はたったの2件</B>。

リツイート企画は、参照系のAPIの制限が厳しく、それを回避しながらプログラムを書くのが面倒だなと思って、手動でやってしまったので、時間の無駄でした。

<B>プロフィールの表示は多かった</B>ので、そこにリンクを貼って、<B>いかにインパクトのあるプロフィールを作るかが重要なポイント</B>だったようです。

# フォロワーの属性と比率
フォロワー1126人のアカウント名とプロフィール欄にあるキーワードを分析したところ、下記のような結果となりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199506/3077da37-5f80-2b7c-656b-6f27b4e390a7.png)

<B>約4割の472人</B>が<B>「相互フォロー」や「フォロバ」</B>などのキーワードを入れていました。
なお、相互フォローを謳っている人のうち、約12%（57人）の人が、フォロー数よりフォロワー数が1割以上多いという結果でした。
つまり、相互フォローを謳っていても、約1割の人は厳密な相互フォローではないと言うことです。
これはフォロワーの中での集計のため数字が低く出ている可能性がありますが、実際には<B>相互フォローを謳いながらフォロワーの方が圧倒的に多いアカウントも多数存在</B>するようです。

次に多いのが<B>副業系</B>のアカウントで、<B>167人（14.8%）</B>が「副業」、「稼ぐ」、「不労所得」、「権利収入」などのキーワードをプロフィールに入れていました。
そこに<B>投資系</B>のアカウント<B>100人（8.8%）</B>が続きます。「FX」、「投資」、「トレーダー」、「バイナリーオプション」などのキーワードがよく出てきます。
そんなに儲かっているのなら、なぜTwitterで無駄な拡散を行い、熱心にDMを送ってくるのでしょうか。

次に、ゲーム89人（7.9%）、大学69人（6.1%）、アニメ67人（6.0%）、コンサル30人（2.7%）と続きます。
ゲーム、アニメは人気ですね。
コンサルは、副業コンサルの人が多いようなので、副業系に分類してもよいかもしれません。

エロ系は案外少なく、17人（1.5%）でした。エッチなお姉さんからDMがいっぱい来るので、もっといっぱいいるかと思いましたが、DMが多いだけでした。

わざわざプロフィールに「暇」とか「ヒマ」と書いている人が8人ぐらいいましたが、書かなくてもこんなことをやっている時点でヒマなのは分かっています。

# 相互フォローの互恵関係は維持されるのか
では、上記のようなエンゲージメント率が低い人たちは、フォローを維持してくれるのでしょうか。

毎日フォロワーは増えるので、全体のフォロワー数だけ見ていると、減っていることに気づきにくいのですが、実は毎日かなりのフォロワーが減っています。

一日平均で26人ぐらいのフォロワーが離脱します。

フォロワーが減る原因は大きく分けて2つあります。

一つはいわゆるフォローはずしです。フォロー数よりも圧倒的にフォロワー数の方が多くすることで、インフレンサーかのように見せかける方法です。

もう一つは次に紹介するアカウントの停止です。相互フォローをやりすぎて、不審なアカウントとみなされアカウントが一時的にロックされます。

正確な数字は分かりませんが、ざっと見た感じだと、6割以上がアカウントロックでした。
案外フォローはずしをする悪意のユーザーの方が少数派のようです。

# プラットフォーマーの対処はどうだったか
Twitterは、このようなフォロワー数遊びについて、どのような対処をしているのでしょうか。

まず、不審な操作を行ったとして、<B>アカウントを一時的に停止</B>する措置を取っているようです。
ただ、いきなりアカウントを永久に削除する訳ではなく、一時停止です。
reCAPTCHAによって人間の操作であることを確認したり、電話番号によるSMS認証で確認をすれば復活することができます。
[@ise_test](https://twitter.com/ise_test)も何度か一時停止されましたが、なんとか生き残りました。

次に、<B>ツイートの表示</B>アルゴリズムが<B>フォロワー数ではなく、エンゲージメントに比例</B>するようになっているように見えます（裏付けをとった訳ではなく、事象から推定しただけです）。
これによって、単にフォロワー数だけ稼いでも意味がなく、初期のエンゲージメントが高い投稿をしないと拡散できないような仕組みにしているようです。

さすが、長年の運用実績があるプラットフォームなので、昔からよく知られた抜け穴には対処をしているようです。

# 検証結果のまとめ
- 相互フォローでは、インプレッションが伸びないため<B>拡散力は低い</B>。8分の1のフォロワー数でも、真面目に情報発信をしているアカウントの方が、インプレッションもエンゲージメント率も高い。
- 相互フォローでは、<B>プロフィールの閲覧数がかなり高まる</B>。そのため、プロフィールに拡散したいインパクトのある画像を掲載すれば、拡散効果が見込める。
- <B>フォロー＆リツイート企画</B>で、リンクを拡散してもらっても、<B>リンクにアクセスする人は悲しいほど少ない</B>。
- 総合的に見ると、広告を打った方が圧倒的に楽。

# 今後の展望
今後、相互フォローの実験用アカウント（[@ise_test](https://twitter.com/ise_test)）は、<B>量から入って質に転換できるか</B>を実験していきます。
内容を客層に合わせていくのか、それとも、時間をかけて客層自体を変えていくのかは悩みどころですが、いろいろ試行錯誤をしていく必要があるでしょう。

<B>マジメに頑張っているアカウント</B>（[@a_isegawa](https://twitter.com/a_isegawa)）は、これからもそのまま<B>継続</B>していきます。

どっちのアプローチが良いのか、また進展があれば報告します。

# 【付録】実験に用いたコードの紹介
相互フォローの実験は、最初は手動で始めましたが、途中で手に負えなくなって自動化しました。
日によっては100人以上フォロワーが増えたり、70人くらい一気にフォロワーが凍結されたりします。
これを手動でやっていると、鬱々としてくるので、オススメしません。

## 環境
mac OS
python 3.7
brew

## pipenvをインストール

```
brew install pipenv
```

## ソースコードを置く場所を作成
```
mkdir TwitterTools
cd TwitterTools
```

## pythonのバージョンを指定
```
pipenv --python 3.7
```

## 依存するライブラリをインストール
```
pip install requests requests_oauthlib
```

## pipenvを立ち上げ
```
pipenv shell
```

## TwitterAPIに登録する

## TwitterAPIの認証情報を設定する
```
vi config.py
```

```.py
CONSUMER_KEY = "[YOUR_KEY]"
CONSUMER_SECRET = "[YOUR_SECRET]"
ACCESS_TOKEN = "[YOUR_TOKEN]"
ACCESS_TOKEN_SECRET = "[YOUR_TOKEN_SECRET]"
```

## TwitterAPIに認証するコードを書く
```
vi oauth.py
```

```.py
import config
from requests_oauthlib import OAuth1Session

def getClient():
  return OAuth1Session(config.CONSUMER_KEY, config.CONSUMER_SECRET, config.ACCESS_TOKEN, config.ACCESS_TOKEN_SECRET)
```

## 相互フォローのコードを書く
```
vi follow4Follow.py 
```

```.py
import json, time, oauth, sys

#---------------------------------------------------------------
# サブルーチン
#---------------------------------------------------------------
PAGE_SIZE = 5000 #取得数 最大5000
BASE_URL = "https://api.twitter.com/1.1"

twitter = oauth.getClient()

# フォロワーのID一覧を取得
def getFollowerIds():
  res = twitter.get(BASE_URL + "/followers/ids.json", params = {'count' : PAGE_SIZE})
  if 200 == res.status_code:
    body = json.loads(res.text)
    return body["ids"]
  else:
    print("Failed: %d" % res.status_code)
    return None

# フォローしている人のID一覧を取得
def getFriendIds():
    res = twitter.get(BASE_URL + "/friends/ids.json", params = {'count' : PAGE_SIZE})
    if 200 == res.status_code:
      body = json.loads(res.text)
      return body["ids"]
    else:
      print("Failed: %d" % res.status_code)
      return None

# リストをマップに変換
def mapFromList(list):
  mapData = {}
  for data in list:
    mapData[data] = data
  return mapData

# フォローをやめる
def destroyFriendships(userId):
  res = twitter.post(BASE_URL + "/friendships/destroy.json", data = {'user_id' : userId})
  if res.status_code != 200:
    print("Failed: %d" % res.status_code)

# フォローする
def createFriendships(userId):
  res = twitter.post(BASE_URL + "/friendships/create.json", data = {'user_id' : userId})
  if res.status_code != 200:
    print("Failed: %d" % res.status_code)

#---------------------------------------------------------------
# メイン処理
#---------------------------------------------------------------

# フォロワーのID一覧を取得
followerIds = getFollowerIds()
if followerIds is None:
  print("Failed to get Followers Ids.")
  sys.exit(1)
followersMap = mapFromList(followerIds)

# フォローしているユーザーの一覧を取得
friendIds = getFriendIds()
if friendIds is None:
  print("Failed to get Friends Ids.")
  sys.exit(1)

# フォロワーとフォローユーザーの件数を出力
print("followers: %d" % len(followerIds))
print("friends: %d" % len(friendIds))
print("------------------------------------------------")

# アンフォローしたフォロワーを削除
for friendId in friendIds:
  if friendId not in followersMap:
    destroyFriendships(friendId)
    print("destroyed %d" % friendId)
    time.sleep(5)

# フォローしてくれた人をフォローバック
friendsMap = mapFromList(friendIds)
for followerId in followerIds:
  if followerId not in friendsMap:
    createFriendships(followerId)
    print("followed %d" % followerId)
    time.sleep(5)
```

上記のコードは、フォローを外した人や凍結された人を削除、フォローしてくれた人をフォローバックするというものです。
コマンド実行するだけなので、シェルスクリプトっぽい書き方にしてみました。

フォロー関連のAPIのドキュメントはこちら。
https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference

```GET followers/list```でもフォロワーの一覧を取得できるが、一度に200件しか取得できない上、リクエスト数の制限が非常に厳しいため、無料ではほぼ使い物になりません。

他方で、```GET followers/ids```のように、ID一覧を取得するAPIは、一度に5000件取得できるため、リクエスト数を減らすことができ、制限にひっかかりにくくなりません。

## 相互フォローのコードを実行
```
python follow4Follow.py 
```

コードの紹介は以上です。

## 参考サイト
TwitterのDeveloperサイト
https://developer.twitter.com/content/developer-twitter/ja.html

Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ　※2019年8月時点の情報
https://qiita.com/kngsym2018/items/2524d21455aac111cdee

Pythonでサクッと簡単にTwitterAPIを叩いてみる
https://qiita.com/ogrew/items/0b267f57b8aaa24f1b73

PythonでTwitter API を利用していろいろ遊んでみる
https://qiita.com/bakira/items/00743d10ec42993f85eb