先日作ったGoogleのインデックスとサイトマップに関するPHPのプログラムを、Herokuにデプロイして自動化してみます。
2024年9月にIndexing APIに変更がありました。使い方を間違えるとスパム扱いするとGoogleのドキュメントに明記されましたのでお気をつけください。この記事はルール変更前に書かれたものです。
個人用のメモ書きの延長なので、フォルダの位置やバージョンなどは必要に応じて適度に読み替えてください。
今回やったこと
この2つの記事で作った2つのプログラムをHerokuに置いて自動実行することです。 両方ともGoogleのインデックスに関するAPIを自動処理するPHPのプログラムです。
使ったもの
- Heroku Free
- Heroku CLI
- Heroku Scheduler
- PHP Composer
Herokuは、FREEプランで動く範囲でやってます。
Windows10+Cmderのコマンドライン環境で実行しました
Herokuのアカウントとプラン
Herokuのアカウントは無料で作れます。
無料のアカウントにクレジットカードを登録すると無料動作枠が1000時間分になりますが、クレジットカードを登録しないと550時間分です。
今回使うHeroku Scheduler
は、クレジットカードの登録済みのアカウントでしか使うことができません。
Heroku Schedulerの動作分も1,000dyno(1,000時間分)の範囲に含まれるので、当面は無料で使えます。(未確認です。8月のBillingで確認予定)
僕は、700円の有料プラン(Hobbyプラン)に乗っけたHeroku Schedulerのほうをメインで使っているのですが、Billingの内容を見ると1か月で$0.07(70円くらい)掛かってます。
契約全体でいうとweb用のdynoと合わせて$7.07です。
Herokuのアカウントはある前提で進めます。ない場合は、新規登録しておいてください。
ここ先インストール作業
ソースコードの準備
必要なものは、ソースコード(PHP)2つ、Googleのサービスアカウントの認証ファイル(JSON)が1つ、gitignoreファイルとHerokuのProcfileの4つです。
https://github.com/kanaxx/hatenablog-indexing
GIT慣れしてない場合は、zipファイルでダウンロードしても大丈夫です。
以下のディレクトリ構成にします。
GITからダウンロードするディレクトリ:C:\tmp\hatena_indexing
Herokuへデプロイするディレクトリ:C:\hatena_heroku
準備作業
作業用のディレクトリへ行き、gitからcloneしてソースを持ってくるまで
まずは、作業ディレクトリへ行きgithubからコードを持ってきます。
λ cd \tmp λ git clone https://github.com/kanaxx/hatenablog-indexing.git Cloning into 'hatenablog-indexing'... remote: Enumerating objects: 45, done. remote: Counting objects: 100% (45/45), done. remote: Compressing objects: 100% (43/43), done. Uremote: Total 45 (delta 23), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (45/45), done. #確認 λ cd hatenablog-indexing λ ls -al #このファイルがあればOK .gitignore LICENSE Procfile credential-sample.json publish_sitemap_to_indexing_api.php readme.md submit_sitemap.php
Herokuへデプロイするディレクトリを作り、gitから持ってきたファイルをコピーします。
publish_sitemap_to_indexing_api.php
submit_sitemap.php
Procfile
.gitignore
の4つをコピーして、さらに自分のGoogle APIのサービスアカウントの認証用のJSONファイルを置く。
#Heroku用のフォルダ作る λ mkdir C:\hatena_heroku #ここを起点 λ cd c:\tmp\hatenablog-indexing\ #ファイルコピー λ cp publish_sitemap_to_indexing_api.php C:\hatena_heroku\ λ cp submit_sitemap.php C:\hatena_heroku\ λ cp Procfile C:\hatena_heroku\ λ cp .gitignore C:\hatena_heroku\ λ ls -al total 21 drwxr-xr-x 1 user 197613 0 Jul 5 11:32 ./ drwxr-xr-x 1 user 197613 0 Jul 5 11:20 ../ -rw-r--r-- 1 user 197613 10 Jul 5 11:26 .gitignore -rw-r--r-- 1 user 197613 44 Jul 5 11:26 Procfile -rw-r--r-- 1 user 197613 2319 Jul 5 11:26 credential.json -rw-r--r-- 1 user 197613 3508 Jul 5 11:26 publish_sitemap_to_indexing_api.php -rw-r--r-- 1 user 197613 3521 Jul 5 11:26 submit_sitemap.php
Google Client Libraryをインストール
#google client libraryをインストール λ composer require google/apiclient:"^2.0" ./composer.json has been created Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 16 installs, 0 updates, 0 removals - Installing ralouphie/getallheaders (3.0.3): Loading from cache - Installing psr/http-message (1.0.1): Loading from cache - Installing guzzlehttp/psr7 (1.6.1): Loading from cache - Installing guzzlehttp/promises (v1.3.1): Loading from cache - Installing symfony/polyfill-php72 (v1.17.0): Loading from cache - Installing symfony/polyfill-mbstring (v1.17.1): Loading from cache - Installing symfony/polyfill-intl-idn (v1.17.1): Loading from cache - Installing guzzlehttp/guzzle (6.5.5): Loading from cache - Installing phpseclib/phpseclib (2.0.27): Loading from cache - Installing psr/log (1.1.3): Loading from cache - Installing monolog/monolog (2.1.0): Loading from cache - Installing firebase/php-jwt (v5.2.0): Loading from cache - Installing google/apiclient-services (v0.139): Loading from cache - Installing psr/cache (1.0.1): Loading from cache - Installing google/auth (v1.9.0): Loading from cache - Installing google/apiclient (v2.5.0): Loading from cache (省略します) Writing lock file Generating autoload files #この2行が出ればOK #確認 λ ls -la total 62 drwxr-xr-x 1 user 197613 0 Jul 5 11:39 ./ drwxr-xr-x 1 user 197613 0 Jul 5 11:34 ../ -rw-r--r-- 1 user 197613 10 Jul 5 11:26 .gitignore -rw-r--r-- 1 user 197613 44 Jul 5 11:26 Procfile -rw-r--r-- 1 user 197613 62 Jul 5 11:35 composer.json -rw-r--r-- 1 user 197613 34030 Jul 5 11:39 composer.lock -rw-r--r-- 1 user 197613 2319 Jul 5 11:26 credential.json -rw-r--r-- 1 user 197613 4215 Jul 5 11:26 publish_sitemap_to_indexing_api.php -rw-r--r-- 1 user 197613 3521 Jul 5 11:26 submit_sitemap.php drwxr-xr-x 1 user 197613 0 Jul 5 11:39 vendor/ #composer.jsonとcomposer.lockができていて #vendorのディレクトリができてればOK
Herokuにアプリを作る
PHPをデプロイする先をHerokuに作ります。この作業はブラウザでやります。
create new appで新規アプリを作る画面を開き、
何も入れずにCreate Appを押す。何も入れなかったら勝手にApp nameを付けてくれる
scenic-saguaro-44740
という名前でApplicationが作られました。この名前は都度変わるので自分の名前を憶えておきましょう。
Herokuへのデプロイは、Heroku GIT
で行います。1、2、3のコマンドを後で使います。
Herokuへデプロイ
やっとHerokuへデプロイします。やることはシンプルです。Heroku Gitのデプロイ手順通りにコマンド打つだけです。
#起点のディレクトリにいき λ cd C:\hatena_heroku #まずログイン(ブラウザが立ち上がる) λ heroku login heroku: Press any key to open up the browser to login or q to exit: Opening browser to https://cli-auth.heroku.com/auth/cli/browser/xxx-xxx-xxx-xxx-xxx Logging in... done Logged in as xxx@gmail.com #作業ディレクトリでgit init λ git init Initialized empty Git repository in C:/hatena_heroku/.git/ #作成したappのgitのURLを設定 λ heroku git:remote -a scenic-saguaro-44740 set git remote heroku to https://git.heroku.com/scenic-saguaro-44740.git #ソースをadd λ git add . warning: LF will be replaced by CRLF in composer.json. The file will have its original line endings in your working directory. warning: LF will be replaced by CRLF in composer.lock. The file will have its original line endings in your working directory. warning: LF will be replaced by CRLF in credential.json. The file will have its original line endings in your working directory. #ソースをコミット λ git commit -am "first commit" [master (root-commit) 7240b39] first commit 6 files changed, 1210 insertions(+) create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 credential.json create mode 100644 publish_sitemap_to_indexing_api.php create mode 100644 submit_sitemap.php #コミットしたファイルをデプロイ! λ git push heroku master Counting objects: 8, done. Delta compression using up to 4 threads. Compressing objects: 100% (7/7), done. Writing objects: 100% (8/8), 9.33 KiB | 2.33 MiB/s, done. Total 8 (delta 1), reused 0 (delta 0) remote: Compressing source files... done. remote: Building source: remote: remote: -----> PHP app detected remote: -----> Bootstrapping... remote: -----> Installing platform packages... remote: NOTICE: No runtime required in composer.json; requirements remote: from dependencies in composer.lock will be used for selection remote: - php (7.4.7) remote: - apache (2.4.43) remote: - nginx (1.18.0) remote: -----> Installing dependencies... remote: Composer version 1.10.7 2020-06-03 10:03:56 remote: Loading composer repositories with package information remote: Installing dependencies from lock file remote: Package operations: 16 installs, 0 updates, 0 removals remote: - Installing phpseclib/phpseclib (2.0.27): Downloading (100%) remote: - Installing psr/log (1.1.3): Downloading (100%) remote: - Installing monolog/monolog (2.1.0): Downloading (100%) remote: - Installing ralouphie/getallheaders (3.0.3): Downloading (100%) remote: - Installing psr/http-message (1.0.1): Downloading (100%) remote: - Installing guzzlehttp/psr7 (1.6.1): Downloading (100%) remote: - Installing symfony/polyfill-php72 (v1.17.0): Downloading (100%) remote: - Installing symfony/polyfill-mbstring (v1.17.1): Downloading (100%) remote: - Installing symfony/polyfill-intl-idn (v1.17.1): Downloading (100%) remote: - Installing guzzlehttp/promises (v1.3.1): Downloading (100%) remote: - Installing guzzlehttp/guzzle (6.5.5): Downloading (100%) remote: - Installing psr/cache (1.0.1): Downloading (100%) remote: - Installing firebase/php-jwt (v5.2.0): Downloading (100%) remote: - Installing google/auth (v1.9.0): Downloading (100%) remote: - Installing google/apiclient-services (v0.139): Downloading (100%) remote: - Installing google/apiclient (v2.5.0): Downloading (100%) remote: Generating optimized autoload files remote: -----> Preparing runtime environment... remote: NOTICE: No Procfile, using 'web: heroku-php-apache2'. remote: -----> Checking for additional extensions to install... remote: -----> Discovering process types remote: Procfile declares types -> web remote: remote: -----> Compressing... remote: Done: 17.5M remote: -----> Launching... remote: Released v3 remote: https://scenic-saguaro-44740.herokuapp.com/ deployed to Heroku remote: remote: Verifying deploy... done. To https://git.heroku.com/scenic-saguaro-44740.git * [new branch] master -> master ##ここまでくれば完了です。
簡単ですね
デプロイの確認
デプロイしたものをが動くのか確認します。
heroku run bash
でコマンドラインで作業します。
#Herokuのbash起動 λ heroku run bash #PHPのバージョン確認 ~ $ php -v PHP 7.4.7 (cli) (built: Jun 18 2020 13:24:00) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Zend OPcache v7.4.7, Copyright (c), by Zend Technologies ##sitemap apiの動作確認 途中でCTRL+Cで止めてOK ~ $ php submit_sitemap.php "https://kanaxx.hatenablog.jp/sitemap_index.xml" -getting XML >> https://kanaxx.hatenablog.jp/sitemap_index.xml got 8 entries. sitemap URL :https://kanaxx.hatenablog.jp/sitemap_common.xml sitemap URL :https://kanaxx.hatenablog.jp/sitemap_periodical.xml?year=2020&month=7 (省略) ##indexing apiの動作確認 途中でCTRL+Cで止めてOK ~ $ php publish_sitemap_to_indexing_api.php "https://kanaxx.hatenablog.jp/sitemap_index.xml" -getting XML >> https://kanaxx.hatenablog.jp/sitemap_index.xml got 8 entries. sitemap URL :https://kanaxx.hatenablog.jp/sitemap_common.xml sitemap URL :https://kanaxx.hatenablog.jp/sitemap_periodical.xml?year=2020&month=7 (省略) ##heroku bashを抜ける ~ $ exit
(重要)ウェブから参照できないことの確認
今回のアプリはスケジューラで動くバッチプログラムです。ブラウザで参照する必要がないので、閲覧できないように対策しておきます。
特に、credential.json
のファイルがウェブから参照できてしまうと、何が起きるか分かりませんので確認しておいてください。
http://scenic-saguaro-44740.herokuapp.com/credential.json
GitにあげてあるProcfile
で、webのrootディレクトリを/publicに変更してあります。手順通りにやっていれば/publicより上のディレクトリはインターネットから見えないはずです。
Webを使わないのであれば止めておくのが一番安全です。アプリケーションのOverview
のDyno formation
で止めます。
3で右に倒れている(ONの状態の)スイッチを左に倒しOFFにし、「confirm」を押し、OverviewでwebがOFFになっていることを確認しておきます。
止めたあとにブラウザでアクセスするとApplication Errorの画面が表示されるようになります。見えないのが期待値なので、エラーになるのは気にしなくていいです。
ログファイルには、このようなエラーメッセージが出ます。No web process runnning
で503ステータスです。
2020-07-05T07:16:41.243668+00:00 heroku[router]: at=error code=H14 desc="No web processes running" method=GET path="/" host=scenic-saguaro-44740.herokuapp.com request_id=b11a0b60-6ba1-4a1c-8793-818e0a6c03df fwd="122.26.3.129" dyno= connect= service= status=503 bytes= protocol=http
Heroku Schedulerのセットアップ
最後に、Herokuのスケジューラを設定して自動実行を仕掛けます。
Heroku Scheduler Add-onを追加する
アプリのOverviewから、Configure Add-onをクリックする。
"schedule"と入力して、Heroku Schedulerを選択
Provisionボタンを押す
Heroku Schedulerにジョブを追加する
Heroku Schedulerの設定画面を開き
Create Jobを押す
この画面が開くので、2回作業をして2つのジョブを追加します。
sitemap api
Google Search Console API Sitemap は実行回数に制限がないので、Every Hour at
で指定しました。1時間に1回、全てのサイトマップをGoogleにPushします。
Commandには、以下をコピペします。
サイトマップのURLは自分のものに書き換えます。
php submit_sitemap.php "https://kanaxx.hatenablog.jp/sitemap_index.xml"
indexing API
Google Indexing APIは1日あたり200回までの制約があるので、Every day at
でスケジュール設定をしました。
1日1回、指定の時間で更新のあった記事URLを上位200件、GoogleにPushします。時間の指定はUTC(世界標準時間)での設定です。日本時間ではないので、設定した時間まで待っても動かないと慌てないように。
Commandには、以下をコピペします。
サイトマップのURLは自分のものに書き換えます。
php publish_sitemap_to_indexing_api.php "https://kanaxx.hatenablog.jp/sitemap_index.xml"
2つのジョブ定義が終わったら、こんな状態になるはずです。
これで全ての作業が完了です。
今後は、日々何もしなくてもHerokuに乗ってるプログラムが自動的に動き、個別サイトマップのURLと記事ページURLをAPIに投げて、クローラーを呼び込むことができます。
まとめ
PHPのバッチプログラムをHerokuにデプロイする作業をやりました。ここまでやれば、サイトマップとGoogleのインデックス(キャッシュ)に悩まされることはないと思います。
この行為がGoogleに好かれるのか、嫌われるのかは分かりません。参考にしてもよいですが全てに関して自己責任で実施してください。ペナルティに関する責任は負えません。
参考にした資料
特になし