広告/統計/アニメ/映画 等に関するブログ

広告/統計/アニメ/映画 等に関するブログ

キーワードプランナーで大量に取得したキーワード情報Pythonで簡単に集約する

Pythonが例えばどういうときに役に立つか?という事例として、広告のターゲティングやバナーに必要なキーワードをリサーチする場合を考えてみます。

キーワードプランナー

バナーの訴求文言やサーチターゲティング等のキーワードを考えるときに、自分の頭だけで考えるのは賢くありません。先ずは既に存在する競合サイトを分析したり、競合のバナー出稿を確認したりするべきです。

広告会社であれば何かしら競合バナークリエイティブを収拾しているサービスと契約していると思いますが、そのような手段がない場合、少なくともGoogleのキーワードプランナーは誰もが無料で使えるサービスです。

ads.google.com

細かい数値を得るには広告出稿が必要ですが、概算値で良ければその必要はありません

キーワードプランナーで競合サイトの分析をする

例えば自分が人事組織関連のSaaSを提供していたとします。 私はこの分野のことは担当したことがないのでどこが一大勢力なのか知りませんが、

boxil.jp

boxil.jp

などを参考に仮想で競合となる企業のサイトを選定しました

キーワードプランナーの「新しくみつける」からURLをコピペして、候補を探すと、直近1ヶ月等の検索ボリュームが計測できます。

f:id:yyhhyy:20200208155654j:plain

ディレクトリ全体やページ単体指定を必要に応じて使い分けながら、ロボット的に大量に競合となるサービスのURLを押してはリストをダウンロードしていきます。

f:id:yyhhyy:20200208155738j:plain

f:id:yyhhyy:20200208155754j:plain

10ファイルくらいになりました。

f:id:yyhhyy:20200208155807j:plain

もっと真面目に探すと恐らくもっとファイル数は増えるでしょう。 これをエクセルで一枚一枚開いてセルに貼り付けるのは意外と時間がかかります

Pythonを使って簡単な前処理をする

ディレクトリ内のデータをロボット的に読み取る

ファイル数が多い場合、一つ一つファイル名を記述して指定することは非効率です。

globライブラリのglob関数を使いフォルダ内のCSVファイル情報をワイルドカード指定で一覧を取得します。

使い方に不慣れだったので幾つかのブログを参考に使い方を確認しました。

note.nkmk.me

qiita.com

import glob
files = glob.glob('data/*.csv')

これで一覧が取得できました

(files)
['data\\Keyword Stats 2020-02-08 at 14_43_20.csv',
 'data\\Keyword Stats 2020-02-08 at 14_43_43.csv',
 'data\\Keyword Stats 2020-02-08 at 14_44_08.csv',
 'data\\Keyword Stats 2020-02-08 at 14_44_31.csv',
 'data\\Keyword Stats 2020-02-08 at 14_46_29.csv',
 'data\\Keyword Stats 2020-02-08 at 14_48_12.csv',
 'data\\Keyword Stats 2020-02-08 at 14_48_51.csv',
 'data\\Keyword Stats 2020-02-08 at 14_49_14.csv',
 'data\\Keyword Stats 2020-02-08 at 14_49_37.csv',
 'data\\Keyword Stats 2020-02-08 at 14_49_53.csv',
 'data\\Keyword Stats 2020-02-08 at 14_50_56.csv',
 'data\\Keyword Stats 2020-02-08 at 14_51_33.csv',
 'data\\Keyword Stats 2020-02-08 at 14_52_47.csv',
 'data\\Keyword Stats 2020-02-08 at 14_53_11.csv',
 'data\\Keyword Stats 2020-02-08 at 14_53_23.csv',
 'data\\Keyword Stats 2020-02-08 at 14_53_36.csv',
 'data\\Keyword Stats 2020-02-08 at 14_53_46.csv',
 'data\\Keyword Stats 2020-02-08 at 14_54_19.csv']

空のリストを作り、データフレームとして読み込んではリストに追加。最後に1つのデータフレームとして結合します。

この発想はこちらのサイトを参照させて頂きました。

[http://pidgeott0.com/engineer/816/:embed:cite]

list = []
#import numpy as np
import pandas as pd
for f in files:
    list.append(pd.read_csv(f,encoding="utf-16",header=0, skiprows=2,sep='\t'))
df = pd.concat(list)

なおGoogle系のサービスでありがちなのですが、文字コードが「utf-16」と特殊です。私は最初これに気がつくまで随分とかかりました。 また冒頭に説明行が入っているので、2行スキップします。

また、CSVファイルのフリをしていますが、タブ区切りなので区切り文字としてタブを指定する必要があります。

df.head()
Keyword Currency Avg. monthly searches Min search volume Max search volume Competition Competition (indexed value) Top of page bid (low range) Top of page bid (high range) Ad impression share ... Searches: Mar 2019 Searches: Apr 2019 Searches: May 2019 Searches: Jun 2019 Searches: Jul 2019 Searches: Aug 2019 Searches: Sep 2019 Searches: Oct 2019 Searches: Nov 2019 Searches: Dec 2019
0 リンク アンド モチベーション クラウド JPY 該当なし 10 100 14.0 177.0 815.0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 リンク アンド モチベーション モチベーション クラウド JPY 該当なし 10 100 17.0 281.0 1217.0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 motivation cloud JPY 該当なし 100 1,000 20.0 599.0 2235.0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 モチベーション クラウド と は JPY 該当なし 100 1,000 23.0 127.0 2160.0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 モチベーション cloud JPY 該当なし 10 100 36.0 281.0 1143.0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

5 rows × 26 columns

len(df)
9379

9000行からなるリストになりした

データを絞り込む

9000件、指定するわけいにもいきませんし、この中には重複もあります。 サーチボリュームが小さいものは削除すべきでしょう。

df.dtypes
Keyword                          object
Currency                         object
Avg. monthly searches            object
Min search volume                object
Max search volume                object
Competition                      object
Competition (indexed value)     float64
Top of page bid (low range)     float64
Top of page bid (high range)    float64
Ad impression share             float64
Organic impression share        float64
Organic average position        float64
In account?                     float64
In plan?                        float64
Searches: Jan 2019              float64
Searches: Feb 2019              float64
Searches: Mar 2019              float64
Searches: Apr 2019              float64
Searches: May 2019              float64
Searches: Jun 2019              float64
Searches: Jul 2019              float64
Searches: Aug 2019              float64
Searches: Sep 2019              float64
Searches: Oct 2019              float64
Searches: Nov 2019              float64
Searches: Dec 2019              float64
dtype: object

ここでまたトラップですが、「Min search volume」「Max search volume」ともに数値ではなくオブジェクトとして認識されています。

df["Min search volume"] = df["Min search volume"].astype(str).str.replace(',','').astype(int)
df["Max search volume"] = df["Max search volume"].astype(str).str.replace(',','').astype(int)
df.dtypes
Keyword                          object
Currency                         object
Avg. monthly searches            object
Min search volume                 int32
Max search volume                 int32
Competition                      object
Competition (indexed value)     float64
Top of page bid (low range)     float64
Top of page bid (high range)    float64
Ad impression share             float64
Organic impression share        float64
Organic average position        float64
In account?                     float64
In plan?                        float64
Searches: Jan 2019              float64
Searches: Feb 2019              float64
Searches: Mar 2019              float64
Searches: Apr 2019              float64
Searches: May 2019              float64
Searches: Jun 2019              float64
Searches: Jul 2019              float64
Searches: Aug 2019              float64
Searches: Sep 2019              float64
Searches: Oct 2019              float64
Searches: Nov 2019              float64
Searches: Dec 2019              float64
dtype: object

これで整数に変わりました

数値に変換できたことで、絞り込みが可能となります

df_select_1000 = df[df["Min search volume"] >= 1000]
df_select_1000.head()
Keyword Currency Avg. monthly searches Min search volume Max search volume Competition Competition (indexed value) Top of page bid (low range) Top of page bid (high range) Ad impression share ... Searches: Mar 2019 Searches: Apr 2019 Searches: May 2019 Searches: Jun 2019 Searches: Jul 2019 Searches: Aug 2019 Searches: Sep 2019 Searches: Oct 2019 Searches: Nov 2019 Searches: Dec 2019
8 the team JPY 該当なし 1000 10000 54.0 42.0 66.0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
87 hr tech JPY 該当なし 1000 10000 31.0 433.0 1026.0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 ラフール JPY 該当なし 1000 10000 0.0 NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 wevox JPY 該当なし 1000 10000 16.0 399.0 958.0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 geppo JPY 該当なし 1000 10000 15.0 502.0 656.0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

5 rows × 26 columns

len(df_select_1000)
159

これで150行です。玉石混交ですのでこれくらいから絞り込むのは目視が良いでしょう

キーワードだけ取り出して、重複を排除すればキーワードリストの完成です。

pd.DataFrame(df_select_1000["Keyword"].unique())
0
0 the team
1 hr tech
2 ラフール
3 wevox
4 geppo
... ...
124 タイム カード アプリ
125 indeed 求人 掲載
126 勤怠 管理 アプリ
127 タイ 求人
128 タッチ オン タイム ログイン

129 rows × 1 columns

目視の際はエクセルかCSVで見るのが良いでしょう

pd.DataFrame(df_select_1000["Keyword"].unique()).to_excel("df_select_1000.xlsx")