概要
Twitter広告には「興味関心およびフォロワーが似ているアカウントのターゲティング」という広告商品があります。
参考:興味関心およびフォロワーが似ているアカウントのターゲティング
「任意のアカウントのフォロワーと似ているアカウント」に対してターゲティングできることになるのですが、取り扱うドメインの事前知識なしにアカウントを検討するのは難しい場合もあります。
そこでこの記事ではRを用いてツイートのデータを取得・整理し、Twitter広告でターゲティングするアカウントを探索的に検討してみます。
事前の設定
パッケージの読み込み
今回の分析に必要となるRのパッケージを読み込みます。
library(tidyverse) # tidyなデータハンドリング
library(rtweet) # TwitterAPIラッパー
library(igraph) # ネットワーク分析
API周りの認証設定
rtweetパッケージでTwitterAPIをコールするので事前に認証周りの設定をしておきます。
必要なパラメータはTwitter Developerから事前に取得しておきましょう。
appname <- "app_name"
consumer_key <- "consumer_key"
consumer_secret <- "consumer_secret"
access_token <- "access_token"
access_secret <- "access_secret"
twitter_token <- create_token(
app = appname,
consumer_key = consumer_key,
consumer_secret = consumer_secret,
access_token = access_token,
access_secret = access_secret)
ツイートの取得と可視化
今回は「育児」というカテゴリでの架空の出稿を想定して、ツイートデータを取得します。
1) 任意の文字を含める人気のツイートから、アカウントを探す
任意のキーワードを含むツイートを検索し、その中でリツイートの多いツイート順に並び替えてみます。
result <- search_tweets(q = "育児", n = 10000)
result_desc <- result %>%
filter(is_retweet == "FALSE") %>%
arrange(desc(retweet_count)) %>%
slice(1:20) %>%
select(screen_name,text,retweet_count) %>%
mutate(text = str_replace_all(text, regex(pattern = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?"),"")) %>%
mutate(text = str_replace_all(text, regex(pattern ="\n",),"")) %>%
mutate(text = str_to_lower(text))
result_desc
以下のようなツイートが取得できました。リツイート数上位のアカウントは、もしかしたら検索キーワードと関連性の高いアカウントかもしれません。
## # A tibble: 5 x 3
## status_id text retweet_count
## <chr> <chr> <int>
## 1 1359125065674223… 3人の育児をしながら世界で活躍するミランダ・カーが、毎日続け… 7
## 2 1359129308724224… 「家事育児完璧にしろよ」みたいなこと言う男はよほど日頃完璧に… 4
## 3 1359136353582080… 世界一家事育児を分担しない自国のオスシングル家庭の養育費未払… 2
## 4 1359131377040453… 八幡と結婚して子供産まれた後のゆきのんは家事と育児の邪魔だか… 2
## 5 1359129094898675… 産んだ後に引き取って育児の責任を全部引き受ける男性が増えれば… 2
2) 任意の文字を含めるツイートから、フォロワー数の多いアカウントを探す
任意のキーワードを含むツイートを検索し、その中でフォロワー数の多いアカウント順に並び替えてみます。
result <- search_tweets(q = "育児", n = 10000)
result_desc <- result %>%
distinct(text,.keep_all = TRUE) %>%
users_data() %>%
distinct(user_id,.keep_all = TRUE) %>%
arrange(desc(followers_count))%>%
slice(1:200) %>%
select(screen_name,description,followers_count) %>%
mutate(description = substr(description, 0, 30))
result_desc
以下のようなツイートが取得できました。フォロワー数で上位のアカウントはもしかしたら検索キーワードと関連のあるアカウントかもしれません。
## # A tibble: 2,421 x 3
## screen_name description followers_count
## <chr> <chr> <int>
## 1 hTcBbWbLse4Tt… "🌟Twitterのみなさん、こんにちは➰🍀みんなの人気者🌟ナ"… 64667
## 2 rottaik "ろった。漫画家。育児しつつ新連載準備中。『リメイク』『メイク"… 58231
## 3 iitripod "ツイッター歴10年。RT多め。ネトウヨ風リベラル左翼。アンチ"… 54309
## 4 docomo_cs "NTTドコモ公式のお客様サポートアカウントです。\nドコモの商"… 35907
## 5 pp_jiro0 "良夫賢父のビッグダディ" 34890
## 6 terrakei07 "インターネットで文章を書いたり、本を出したり、ラジオで喋った"… 32184
## 7 nandemonai_ni "肩書き不要、なんでもない人間です。2015年2月〜2016年"… 32018
## 8 nuno40801 "北海道の小児科専門医. なるべく根拠に基づいて小児科関連の情"… 20532
## 9 comicessay "WEBマンガ誌「コミックエッセイ劇場」の公式アカウントです。"… 19264
## 10 tobalog "ミニマリストの対岸にいる人。『トバログ』でブログとYouTu"… 18887
## # … with 2,411 more rows
3) ネットワークを可視化して上位のアカウントを探す
任意のキーワードでツイートしている人たちのネットワーク図を可視化し、コミュニティの中心にいるアカウントを把握してみます。
ネットワークグラフを用いることで、リツイートやいいねなどでネットワーク上の上位に存在するアカウントを可視化することができます。
ここではigraphパッケージを利用して「特定のキーワードにおけるリツイート数が多い」アカウントのネットワーク分析を実施します。
result <- search_tweets(q = "育児", n = 10000)
result_retweet_desc <- result %>%
arrange(desc(retweet_count)) %>%
slice(1:100)
# igraphで描画するためにネットワークデータのデータフレームに変換
result_network <- network_graph(result_retweet_desc)
# igraphでプロット
plot(result_network,
vertex.size=8,
vertex.label=V(result_network)$name,
vertex.label.font=2,
vertex.frame.color="white",
vertex.label.cex=0.8,
edge.width=E(result_network)$weight,
layout=layout.fruchterman.reingold
)
いくつかのアカウントをフォローする形で複数のグループで分かれていることが確認できました。ここではリツイート元のアカウントが中心に位置しますが、そのアカウントに注目することで何か気づきが得られるかもしれません。
4) 任意のユーザーのフォロワーを、フォロワーの多い数順で並び替える
任意のアカウントのフォロワーはそのアカウントと関連性が高いかもしれません。そこで任意のアカウントのフォロワーを、フォロワー数の多い順で並び替えてみます。
ここではau公式アカウント(@au_official)を例にして抽出してみます。
coreUserName = "au_support"
user_total <- get_followers(coreUserName, n = 75000)
twitterUser_follower_df <- get_followers(
coreUserName, n = nrow(user_total), retryonratelimit = TRUE
)
twitterUser_follower_df <- lookup_users(twitterUser_follower_df$user_id) %>%
users_data()
## フォロワー数の降順で並び替え
df_check <- twitterUser_follower_df %>%
arrange(desc(followers_count)) %>%
select(screen_name,name,description,followers_count)
目視にてピックアップしたところ、以下のような関連性の高いアカウントを発見することができました。
## screen_name name followers_count
## 1 UQinfo UQ、だぞっ 195185
## 2 WebMoney_INFO auペイメント(WebMoney) 97400
## 3 smartpass_au auスマートパス 91052
## 4 BIGLOBE BIGLOBE 89661
## 5 au_PAY_market au PAY マーケット 23124
## 6 aubookpass ブックパス@au以外も使える! 16848
## 7 utapass うたパス 16349
## 8 up_now_official uP!!!【公式】 9718
## 9 auAM_official auアセットマネジメント 7283
## 10 au_ena auサポーとり エナ 【公式】 5573
## 11 adp_au au Design project 4560
その他、ちょっとした工夫
前処理
APIから取得したツイート情報のデータフレームはそのままでは扱いづらいため、必要に応じて以下のような前処理を実施します。
URL文字列除去
多くのツイートにはURLが含まれていますので、形態素解析する場合には予めURL文字列を除去しておきます。
mutate(text = str_replace_all(text, regex(pattern = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?"),""))
bot除去
人ではなくbotによる自動投稿も少なくないため、Twitterクライアントを判定してbotと思われるレコードを除去します。
filter(source != "twittbot.net")
リツイートの重複排除
リツートが行として重複すると扱いづらいためリツイートのレコードを除去します。
filter(is_retweet == "FALSE")
ノイズとなるアカウントの除去
海外のスパムアカウント等、フォロワー数が多くてもノイズに近いようなアカウントが抽出されることもあります。このため必要に応じて、認証済みアカウントやプロフィールでの公式の文字列の有無をフィルターの条件とします。
filter(verified == TRUE) ## 認証済みアカウント
filter(str_detect(description, "[亜-熙ぁ-んァ-ヶ]")) ## プロフィールでの日本語存在チェック
filter(str_detect(description, "[公式]")) ## 公式の文字列チェック
APIの制約
TwitterAPIにはリクエスト制限があり、APIのレスポンスで Rate limit exceeded
エラーが返ってきたら、それは制限を超えていて利用できない状態になっています。
Rのパッケージであるrtweet
ではrate_limit()
を実行することでAPIの使用状況を確認できます。以下のような形で残リクエスト数が0%ではないエンドポイント一覧を出力可能で、利用可能になるまでの残時間も出せます。
エンドポイントごとの利用状況
rate_limit()
## # A tibble: 220 x 7
## query limit remaining reset reset_at timestamp app
## <chr> <int> <int> <drtn> <dttm> <dttm> <chr>
## 1 lists/l… 15 15 15.01… 2021-02-10 22:06:11 2021-02-10 21:51:11 test…
## 2 lists/m… 75 75 15.01… 2021-02-10 22:06:11 2021-02-10 21:51:11 test…
## 3 lists/s… 15 15 15.01… 2021-02-10 22:06:11 2021-02-10 21:51:11 test…
## 4 lists/m… 900 900 15.01… 2021-02-10 22:06:11 2021-02-10 21:51:11 test…
## 5 lists/s… 15 15 15.01… 2021-02-10 22:06:11 2021-02-10 21:51:11 test…
## 6 lists/s… 75 75 15.01… 2021-02-10 22:06:11 2021-02-10 21:51:11 test…
## 7 lists/o… 15 15 15.01… 2021-02-10 22:06:11 2021-02-10 21:51:11 test…
## 8 lists/s… 180 180 15.01… 2021-02-10 22:06:11 2021-02-10 21:51:11 test…
## 9 lists/m… 15 15 15.01… 2021-02-10 22:06:11 2021-02-10 21:51:11 test…
## 10 lists/s… 900 900 15.01… 2021-02-10 22:06:11 2021-02-10 21:51:11 test…
## # … with 210 more rows
例えば利用中のエンドポイントで絞る場合は以下のようになります。
rate_limit() %>%
filter(limit != remaining)
## # A tibble: 2 x 7
## query limit remaining reset reset_at timestamp app
## <chr> <int> <int> <drtn> <dttm> <dttm> <chr>
## 1 applicat… 180 176 13.46… 2021-02-10 22:05:32 2021-02-10 21:52:05 test…
## 2 search/t… 180 170 14.06… 2021-02-10 22:06:08 2021-02-10 21:52:05 test…
おわりに
実際にターゲティング用途でAPIを利用してみたところ、想定外のアカウントの発見に繋がりました。Twitter広告側でもある程度のユーザー拡張はできるはずですが、最初のアカウント探しという意味ではAPIが活用できそうな印象です。