※当サイト一部記事にはP Rが含まれます

Google検索順位チェック用のSEOツールをPythonで自作して自動化する。

TIPS
この記事は約16分で読めます。

無料の検索順位チェックツール「Serposcope」がエラー…。泣く泣くPythonで書くことに。

 

集客を意識したブログなりサイトなりを運営している人ならば、Googleなどの検索順位のチェックは欠かさず行っていると思います。

しかし、Googleサーチコンソールでは自分のサイト・ブログの順位しか表示されないので、他のサイトを含めた俯瞰的な動きを見ることができなかったりします。そこで、多くのアフィリエイターの方々はGRCなどの検索順位チェックツールを使って、日夜、検索順位の維持に励んでいます。

 

一方、私みたいな趣味ブロガーレベルの人や副業アフィリエイターには、GRCはちょっと手が出しにくかったりします(ライセンス料が高すぎだよ!!)。

そこで、おそらく多くの方々は無料で初心者でも使えるSerposcopeを使っているのではないかと。

 

私も使っていて、自分のサイトの検索順位が時系列で見えたり、他のサイトとの順位や力関係が見えたり、結構便利なんですよね。

 

だがしかし、ある日突然、Serposcopeがブっ壊れました・・・( ノД`)

エラーを出して順位チェックがマトモに動かなくなることがほとんど。サイトやキーワードを登録しすぎたのかもしれません。Serposcopeは無料で無制限にサイト・キーワードを設定できますが、登録しすぎるとおかしくなったり遅すぎて終わらなくなったりするという報告も、たしかどこかで見ましたし…。

 

今からまたGRCを買うのもしゃくなので、Google検索順位チェック用のSEOツールをPythonで自作することにしました。

 

 

シンプルなSEOツールを作る。Google検索順位チェックツールのコンセプト。

今回作ろうとしているSEOツールの概要を最初に書きます。超シンプルですよ。

 

指定したキーワードの上位XX件に表示されているサイトの情報をスクレイピングしてくる。【本記事コンテンツ】

引数またはクリップボードからキーワードを指定して、検索順位を調査して上位XX件の全サイトのURL・タイトル(titleタグ)・見出し内容(h1~h3の内容)・文字数などを抽出してCSVファイルに出力します。これを定期的に自動実行させてデータを貯めていきます

こんなの↓。

 

タイトルタグや見出しタグの内容まで拾っている理由は2つあります。1つは、検索順位が大きく上がったサイトなどが出た場合、具体的に見出しやタイトルの内容や、含まれるキーワードがどのように変わったのか、差分を自動検知するためです。もう1つは後述。

他にも取った方が良い情報はいくつか思い当たりますが、初期バージョンはこんなもんにしておきます。また、作っていくうちに追加していくかも~。

 

SEOのマニュアル定常チェックは時間の無駄。スクレイピングしてきたデータを時系列比較してアラートを上げる。【次回記事予定】

定期的に自動実行させて貯まったデータを時系列比較して、自分のサイトの順位が大きく下がったり、圏外からジャンプアップしてきたライバルサイトなどが出てきた場合に、メールでアラートを上げます

 

例えば、Google Analytics、Search Console、Google AdSenseとかを毎日眺めるのは、時間の無駄です。こういうツールは基本的に「何か問題が起こったときのためのもの」なんですよね(立ち上げたばかりのサイトの場合は話が別です)。

「バズって急にアクセスが増えた」「WordPressに不正アクセスなどがないか」「おかしな流入元からのアクセスがないか」「Search Consoleでエラーが出てる」「Adsenseで無効クリックや異常クリックが発生してないか」など。こういうのは自動巡回ロボットを作っておいてプログラムに定常監視させておき、問題があるときだけアラートを上げるようにした方が効率的です。基本的に人間が見なければならないのは、異常が発生したときだけ。

 

同様の理由で検索順位のチェックも、いちいち人間が手動で定期的にチェックするのは効率が悪いです。そんな管理業務に時間を使う暇があるなら1本でも記事を書いた方がいい。そういう意味で「アラートの機能」は非常に重要になります。自動化の時代に中間管理職はいりません!ということですw。

これは続編記事で書く予定。えっ?いつになるかって?それはこの記事のアクセス数次第さ!w

 

ちなみにSerposcopeにはアラートがないんですよね( ノД`)。GRCは細かくアラート設定できるのに。やっぱり、GRCは機能がすげえよ…。

 

サジェストワード・関連語・共起語の自動抽出と集計【次々回?】

タイトル・見出しの内容を抽出するもう1つの理由としては、検索上位に表示されているサイトのキーワードの関連語・共起語の抽出と集計を自動化する機能をこれから作りたいと思っているからです。

Pythonの場合、Janomeという日本語形態素解析ライブラリが簡単に使えるので、対象キーワードで、どんな共起語がどのくらいの頻度で使用されているかを集計できるかどうか試してみたいです。

 

こういうサンプルプログラムを作ってる人は多そう。これから、ちょっと知見を調べてみようと思います。

もしかすると先々には、以下記事で書いたサジェストキーワードのグルーピング・検索意図の類推まで、全自動でできるようになるかもしれませんね。もう、SEOの初期リサーチは人工知能で完全自動化できる時代が近づいているのかもです。

ブログキーワード選定の具体例&失敗例【事例付き】。SEOセオリー誤解してない?
ブログのキーワード選定具体例&失敗例まとめ。実際に本弱小雑記ブログで強豪キーワードを狙いましたw。 SEOキーワード選定シリーズの記事第二弾になります~^^。前回記事はコチラ。 今回は実際に具体例&失敗例を出しながら、キーワード選定の重要な...

 

 

【全ソースコード】指定キーワードの検索上位に表示されている人気サイトのタイトルや見出しを全部ブッコ抜くPythonスクリプト。

最初にソースコード全文を掲載します(ダブルクリックすると、コピペできます)。

基本的にBeautifulSoupを使って、必要な項目を取っているだけのシンプルなプログラムです。Pythonはこういうのが時間かけずにサクっと作れるのが有難いですね。

当方環境

Windows10

Python 3.6.4

pip install必要

beautifulsoup4

requests

pyperclip(クリップボード使わないなら不要)

pyinstaller(後でEXE化しないなら不要)

import sys
import pyperclip
import requests
import bs4
import csv
import datetime

#置換用
def replace_n(str_data):
	return str_data.replace('\n', '').replace('\r', '')

#コンカチ用
def concat_list(list_data):
    str_data = ''
    for j in range(len(list_data)):
        str_data = str_data + replace_n(list_data[j].getText()) + ' / '
    return str_data

#出力データ
output_data = []
output_data.append(['検索順位', 'サイトURL', 'TITLEタグ', 'H1タグ', 'H2タグ', 'H3タグ', '記事文字数'])

#キーワードの受け取り(引数から。なければクリップボードから)
if len(sys.argv) > 1:
    search_url_keyword = ' '.join(sys.argv[1:])
else:
    search_url_keyword = pyperclip.paste()

#検索順位取得処理
if search_url_keyword and search_url_keyword.strip():
    #Google検索の実施
    search_url = 'https://www.google.co.jp/search?hl=ja&num=50&q=' + search_url_keyword
    res_google = requests.get(search_url)
    res_google.raise_for_status()

    #BeautifulSoupで掲載サイトのURLを取得
    bs4_google = bs4.BeautifulSoup(res_google.text, 'html.parser')
    link_google = bs4_google.select('div > h3.r > a')
    for i in range(len(link_google)):
        #なんか変な文字が入るので除く
        site_url = link_google[i].get('href').split('&sa=U&')[0].replace('/url?q=', '')
        if 'https://' in site_url or 'http://' in site_url:
            #サイトの内容を解析
            try:
                res_site = requests.get(site_url)
                res_site.encoding = res_site.apparent_encoding
            except:
              continue
            bs4_site = bs4.BeautifulSoup(res_site.text, 'html.parser')

            #データを初期化
            title_site = ''
            h1_site = ''
            h2_site = ''
            h3_site = ''
            mojisu_site = 0

            #データを取得
            if bs4_site.select('title'):
                title_site = replace_n(bs4_site.select('title')[0].getText())
            if bs4_site.select('h1'):
                h1_site = concat_list(bs4_site.select('h1'))
            if bs4_site.select('h2'):
                h2_site = concat_list(bs4_site.select('h2'))
            if bs4_site.select('h3'):
                h3_site = concat_list(bs4_site.select('h3'))
            if bs4_site.select('body'):
                mojisu_site = len(bs4_site.select('body')[0].getText())

            #データをリストに入れておく
            output_data_new = i+1, site_url, title_site, h1_site, h2_site, h3_site, mojisu_site
            output_data.append(output_data_new)

#CSVファイルに出力する
now = datetime.datetime.now()
csv_file = open('[' + search_url_keyword + ']' + '{0:%Y%m%d%H%M%S}'.format(now) + '.csv', 'w', encoding='UTF-8')
csv_writer = csv.writer(csv_file, lineterminator='\n')
for j in range(len(output_data)):
    csv_writer.writerow(output_data[j])
csv_file.close()

 

 

【ソースコード解説】実装のポイントの説明と解説。

検索キーワードの受け取り。引数またはpyperclipでクリップボード。

if len(sys.argv) > 1:
    search_url_keyword = ' '.join(sys.argv[1:])
else:
    search_url_keyword = pyperclip.paste()

プログラム実行時に引数があれば、その値をキーワードに、なければクリップボードから取得してます。

これは自動実行で使うだけでなく、ネットを見ているときに「おっ、このキーワードどうなんだろ?」って思ったときに、コピペからexeダブルクリックで手軽に検索結果を取得できるようにしたいがためにこんなことしてます。不要な人は引数だけで。

なお、入力値検証などはしてないので、ちゃんと作りたい人は自分でちゃんとやってください(たぶんファイルに使えない文字列とかだとエラーになります)。

 

対象キーワードでGoogle検索した後、BeautifulSoupでサイトURLの抽出。

search_url = 'https://www.google.co.jp/search?hl=ja&num=50&q=' + search_url_keyword

《省略》
bs4_google = bs4.BeautifulSoup(res_google.text, 'html.parser')
link_google = bs4_google.select('div > h3.r > a')
for i in range(len(link_google)):
    #なんか変な文字が入るので除く
    site_url = link_google[i].get('href').split('&sa=U&')[0].replace('/url?q=', '')

requestsでgoogle検索を行います。「num=50&」の部分が検索上位XX件の部分です。100位まで取る場合は「num=100&」に変更してください。もし、User-Agentを偽装する場合は、ここでリクエストヘッダに付けてください。

サイトURLの抽出はセレクタで指定してます。これはhtmlを解析してください。Google検索結果ページのデザインなどが変わったら変更になるかも。

また、取れてくるURLに余計なパラメータが付いてるのでreplaceしてます。かっこよく決めたい人は正規表現で抽出するとかしてね(要import re)。

 

検索結果に出たページのリクエストを取得。

try:
    res_site = requests.get(site_url)
    res_site.encoding = res_site.apparent_encoding
except:
  continue

個別ページについては、404とかでサイトが消えて存在しない可能性もあるので、raise_for_statusとせずに、try~except continueで逃がしてます。これはエラー発生でいちいちプログラムが止まってたらお話にならないからです。エラーの場合はそのままスキップして次に行きます。

また、各ページのエンコードによっては文字化けするので、apparent_encodingを入れてます。

 

ページのhtmlをセレクタ指定で抽出してリストに入れていく。

if bs4_site.select('title'):
    title_site = replace_n(bs4_site.select('title')[0].getText())
if bs4_site.select('h1'):
    h1_site = concat_list(bs4_site.select('h1'))
if bs4_site.select('h2'):
    h2_site = concat_list(bs4_site.select('h2'))
if bs4_site.select('h3'):
    h3_site = concat_list(bs4_site.select('h3'))
if bs4_site.select('body'):
    mojisu_site = len(bs4_site.select('body')[0].getText())

必要な物をひたすらconcatしてリストに入れていきます。concat_listは上の方にあるdefです。

文字数はbodyタグ内の文字数という超いい加減仕様w。実際の記事の文字数はこれよりずっと少ないよねw。まあ、目安ということで。

 

CSVファイルに出力。

now = datetime.datetime.now()
csv_file = open('[' + search_url_keyword + ']' + '{0:%Y%m%d%H%M%S}'.format(now) + '.csv', 'w', encoding='UTF-8')
csv_writer = csv.writer(csv_file, lineterminator='\n')
for j in range(len(output_data)):
    csv_writer.writerow(output_data[j])
csv_file.close()

検索キーワードと日付をファイル名に入れて、CSV作成しています。Windowsなので出力時にエラーになる場合を考慮し、UTF-8指定にしてます。このCSVファイルを文字コード変えずにEXCELとかで開くと文字化けるので注意。

別にCSVでなくても、TXTに出してもいいですし、DBに入れてもいいです。私はMySQLに入れようかなぁ…。

 

 

作ったスクリプトの実行ファイル化・自動実行設定(Windowsならバッチにしてタスクスケジューラ)。

実行ファイル形式(EXE化)にしたい場合はpyinstallerなどを使う。

pyinstaller google_check.py –onefile –noconsole

実行ファイル形式にしてダブルクリックで使いたい人は、pyinstallerでEXEファイルを作っておきましょう。PythonスクリプトのEXE化ツールはいくつかありますけど、Pythonのバージョンに引きずられるものが多いので、バージョンを要チェック。

裏で勝手に取っておいてほしいので、「–noconsole」指定にしてます。黒い窓が出るのが好きな人は外してくださいw。

 

Windowsなら調べたいキーワードリストでbatファイルを作成+タスクスケジューラで定期的自動実行。

U:\google_check.exe Serposcope
U:\google_check.exe 検索順位
U:\google_check.exe 検索順位 ブログ

Windowsで自動実行なら手軽なタスクスケジューラですね。上記のように調べたいキーワードを引数にしたリストで.batファイルを作っておくと便利です。あとは作ったバッチファイルをタスクスケジューラで週1回自動実行とかに設定しておくだけ。

 

以上です!。

非常に簡単にできましたね^^。画面操縦系はUWSCのが便利だけど、スクレイピングやその他の簡単なプログラムはPythonで作るとすごーく短時間で作れちゃう。めっちゃ便利!(^^)!。

次回は検索順位の時系列比較+アラート編の予定(「検索順位」に限定しないなら、なんか似たようなのが既にありそうだよねw)。時期は未定~。

 

 

【2018/11/22追記】注意喚起。Google検索で画像認証(reCAPTCHA)が表示されるケースがあるとのこと。

私の環境では発生していないので確たることは言えないのですが、当ブログ読者様から情報共有いただき、Google検索で画像認証(reCAPTCHA)が表示されてしまい情報取得がうまくいかないケースがあるとのことです(Googleから不振なアクセスと判定されてしまうケースのようです。)。

念のため注意喚起のため記事に追記させていただきました。

・【参考】「ご利用のコンピュータ ネットワークから通常以上のトラフィックが検出されました」 – Google 検索 ヘルプ –

 

「どうしても自分で解決できない!」という方は諦めて「GRC」を使ってくださいな