キーワードプランナーで大量に取得したキーワード情報Pythonで簡単に集約する
Pythonが例えばどういうときに役に立つか?という事例として、広告のターゲティングやバナーに必要なキーワードをリサーチする場合を考えてみます。
キーワードプランナー
バナーの訴求文言やサーチターゲティング等のキーワードを考えるときに、自分の頭だけで考えるのは賢くありません。先ずは既に存在する競合サイトを分析したり、競合のバナー出稿を確認したりするべきです。
広告会社であれば何かしら競合バナークリエイティブを収拾しているサービスと契約していると思いますが、そのような手段がない場合、少なくともGoogleのキーワードプランナーは誰もが無料で使えるサービスです。
細かい数値を得るには広告出稿が必要ですが、概算値で良ければその必要はありません
キーワードプランナーで競合サイトの分析をする
例えば自分が人事組織関連のSaaSを提供していたとします。 私はこの分野のことは担当したことがないのでどこが一大勢力なのか知りませんが、
や
などを参考に仮想で競合となる企業のサイトを選定しました
キーワードプランナーの「新しくみつける」からURLをコピペして、候補を探すと、直近1ヶ月等の検索ボリュームが計測できます。
ディレクトリ全体やページ単体指定を必要に応じて使い分けながら、ロボット的に大量に競合となるサービスのURLを押してはリストをダウンロードしていきます。
10ファイルくらいになりました。
もっと真面目に探すと恐らくもっとファイル数は増えるでしょう。 これをエクセルで一枚一枚開いてセルに貼り付けるのは意外と時間がかかります
Pythonを使って簡単な前処理をする
ディレクトリ内のデータをロボット的に読み取る
ファイル数が多い場合、一つ一つファイル名を記述して指定することは非効率です。
globライブラリのglob関数を使いフォルダ内のCSVファイル情報をワイルドカード指定で一覧を取得します。
使い方に不慣れだったので幾つかのブログを参考に使い方を確認しました。
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")