ぃまだWordPressで消耗してるよっ!

2015年末の状況ですので、今現在は変更されている可能性が多分に含まれます。
VCCW(VirtualBox・Vagrant)・WP-CLI・Wordmove・Gulp などのそれぞれのインストールと基本的な使い方は他のサイトにて確認下さい。
および、内容に未確定な内容を多く含みます。

最もよく見られた投稿をJetpack APIから取得

プラグインだと WP Most Popular が該当すると思う。
一時期導入していたが、都度アクセスログをMySQLにINSERTする模様で1 、ちょっと抵抗があった。
その後、何度かのWordPress入れ替えを期に、このプラグインは使わなくなった。

一方、統計情報はGoogleアナリティクスが代表的かと思うが、如何せん、覚える事が多過ぎて設定まではしたが、その後の操作やチューニング?はスルーしていた…生業にしていないのと、そんなに全くアクセス数を気にする程のブログじゃないので。
その後、Jetpackを導入してStatsがお手軽で良いなぁという事で、ダッシュボードからも統計情報が見る事ができるので、こちらを使用している。

で、何時頃からか WP REST API が出てきて、今に至る、と。

この統計情報を定期的・自動的に取得する事2 ってできないかと調べてヒットしたのが GET /sites/$site/stats/top-posts で、このAPIを発行するには、OAuth2 Authentication を事前に発行する必要がある…と。

つまりこれはTwitterのoauth2と同様の事を行えば良いの?(疑問形)という事で実際にコーディング…の前に WordPress.com の Applications Manager にてアプリケーションの登録と言うか何と言うか、を行う。3
この操作で分かっていないのが「Javascript Origins」項目で、少なくとも今回の件に関してはJavascriptは関与しないので(Ajaxでどうのこうの、の場合なのかなぁ?)、未入力、他はTwitterの場合と同様。

ところで今更だが、このブログはWordPress.comの上に乗って独自(サブ)ドメインを割り当てているのではなく、レンタルサーバを利用しているという事、および、このブログを REST API にするのではなく、あくまでもWordPress.comのJetpackのStatsをこちら側に持って来れたら良いなぁという事で、何の事かと言うと、この辺りの情報をWeb検索しても自分が立ち上げたWordPressサイトをAPI化する、みたいな記事が多く、そうじゃぁ無いですよ、という事で。

さて、プログラムの構造は、このブログへのアクセス時にWordPress.comへ情報を都度取得するのでは無く、

  1. cronで1回/日、WordPress.comへアクセスして情報を取得、その情報をファイル書き出しするプログラムをWeb公開領域外に作成
  2. このブログへのアクセス時はその書き出したファイルを元に情報を展開するWordPressのショートコードを作成

…としており、この構造はトップページにあるであろうツイートも同様の仕組みで、ただしこちらは一日に何度か取得しているが。
このブログ程度(アクセス数はお察し)だと都度WordPress.comにアクセスしても問題にならない気もするけど一応礼儀として1回/日にしている。
元々ロングスパンな統計情報が欲しかったので、炎上でもしない限り順位がそう簡単に入れ替わると思えず、1回/日で充分かと思っている。

実際のコーディングだが、躓いた…ので、色々Web検索してヒットしたのが Get The Most Popular Posts From The WordPress API – Eric L. Barnes で、これはクラス化されているけど、基本はこの流れ。

define('WP_OAUTH2_ENDPOINT', 'https://public-api.wordpress.com/oauth2/token');
define('MY_CLIENT_ID', '******');
define('MY_CLIENT_SECRET', '******');
define('MY_WP_USERNAME', '******');
define('MY_WP_PASSWORD', '******');
define('WP_API_TOP_POSTS_TEMPL', 'https://public-api.wordpress.com/rest/v1.1/sites/%s/stats/top-posts?period=%s&num=%s&max=%s');
define('WP_API_TOP_POSTS_SITE', '******');
define('WP_API_TOP_POSTS_PERIOD', 'year');
define('WP_API_TOP_POSTS_NUM', '1');
define('WP_API_TOP_POSTS_MAX', '10');

$curl = curl_init(WP_OAUTH2_ENDPOINT);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, array(
  'client_id' => MY_CLIENT_ID,
  'client_secret' => MY_CLIENT_SECRET,
  'grant_type' => 'password',
  'username' => MY_WP_USERNAME,
  'password' => MY_WP_PASSWORD,
));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$auth = json_decode(curl_exec($curl));
$access_token = $auth->access_token;

$context = stream_context_create(array(
  'http' => array(
    'ignore_errors' => true,
    'header' => array (
      0 => sprintf('authorization: Bearer %s', $access_token),
    ),
  ),
));
$response = file_get_contents(
  sprintf(WP_API_TOP_POSTS_TEMPL
    ,WP_API_TOP_POSTS_SITE
    ,WP_API_TOP_POSTS_PERIOD
    ,WP_API_TOP_POSTS_NUM
    ,WP_API_TOP_POSTS_MAX),
  false,
  $context
);
$response = json_decode($response, true);

foreach ($response['days'] as $key1 => $value1) {
  foreach ($value1['postviews'] as $key2 => $value2) {
    foreach ($value1['postviews'] as $key2 => $value2) {
      if ('post' !== strtolower($value2['type'])) {
        continue;
      }
      // 色々と
    }
  }
}

認証と統計情報取得とその情報の加工、加工した情報の保存(割愛)から成り立っている。

認証に関して、WP_OAUTH2_ENDPOINTMY_CLIENT_IDMY_CLIENT_SECRET はWordPress.comの Applications Manager で発行された値、MY_WP_USERNAMEMY_WP_PASSWORD はWordPress.comへのログインIDとパスワードになる。
これらの値を元に認証、$access_token$auth->access_token)を取得して、次の統計情報取得APIを発行する時の参照値としている模様。
この統計情報取得API発行時の WP_API_TOP_POSTS_SITE は、自分のドメインURLと言うか、WordPress.com上で統計情報画面のURLを見れば分かるかと思う…自分の場合は morry.duelist.org になる。

余談だが、コーディング中に何度もWordPress.comにアクセスするのも嫌なので、上記$responseが正常に取得できた事を確認した時点で、この変数をシリアライズしてファイル保存、以降は上記のコードをコメントアウト、この保存したデータを元にforeachしてコーディングを続行、と言う事で、PHP、配列をそのままファイルに保存|マコトのおもちゃ箱 ~ぼへぼへ自営業者の技術メモ~ などを参照。

// シリアライズを一度行うよ
file_put_contents("hoge.dat", serialize($response));
// コーディング中はこちらを使用
$response = unserialize(file_get_contents("hoge.dat"));

および、$responsejson_decodeされる時の第2引数をtrueにしておかないと、ちょっと辛いかも。

このforeachしているデータだが、投稿(post)も固定ページ(page)も同一条件でカウントされる。
自分の場合、「投稿」しか必要無いので WP_API_TOP_POSTS_MAX を多目に取って必要件数、現状では5件だけ取得している。

続いてWordPressのショートコードになるが、ループ外のpost_idから各種付帯情報を取得する必要があった。
と言うのは、統計情報取得APIで取得できる値にタグや抜粋が含まれていないので…この辺りはケースバイケースかと思うが、ある情報はこちらから、ある情報はWordPressで、というのも気持ち悪いので、post_idのみを参照する事にした。
下記は post_id(int)$value['id']) を元に各種投稿情報を取得するための…で問題無いのかなぁ…大まかな流れ…だけど、うーん…何と言うか…何かこう落ち着かないコーディングというか…Staticおじさん脳は自粛…

$my_posts = new WP_Query(sprintf('p=%d', (int)$value['id']));
if ($my_posts->have_posts()) {
  while ($my_posts->have_posts()) {
    $my_posts->the_post();
    $tmp1 = get_the_excerpt();              // 抜粋
    $tmp2 = get_permalink();                // パーマリンク
    $tmp3 = the_title('', '', false);       // タイトル
    $tmp4 = get_post_time('Y/m/d');         // 日付
    $tmp5 = get_the_tag_list('', ', ', ''); // タグリスト
  }
}

ちなみに。
自分のブログで最も読まれているロングテール何それなページビュー割合の投稿は、このリストから明示的に除外している。
具体的には、統計情報取得APIで取得したデータで該当する記事のpost_id(int)$value2['id'])はスルー(continue)というオンコーディング…post_idって変わらないと思っているが…
このショートコードはトップページ程度からしか発行しない予定だけど、一番読まれている投稿が、どう考えてもトップページの一番最初に出てくるのはちょっと良識を疑われると言うか何と言うか…4 だったので。

および。
せっかくなのでこのショートコードを404ページでも表示しようかと思ったが、テーマのテンプレートからどうやって…でヒットしたのが、WordPress – ショートコードをテーマファイルで使用する方法 | Technolog.jp – ICTウェブマガジン

<?php echo do_shortcode( '[SHORTCODE]' ); ?>

2016/03/10

Menu of this post

  1. 1. だらだらと
  2. 2. WP-CLI・Wordmove
  3. 3. 最もよく見られた投稿をJetpack APIから取得
  4. 4. 関連する投稿を実装してみる
  5. 5. その他の細々とした改修

Footnotes

  1. 1. このプラグインではなかったかもしれないのと、深く潜った訳では無いので記憶あやふや。

  2. 2. 以前この統計情報をCSVでダウンロードできた気がしたのだが…一度だけ試しに操作したのだが…操作方法を忘れた…と言うか、ダッシュボードからもWordPress.comからもできない?

  3. 3. 凄く曖昧な事を書くと、ここで登録されたアプリ情報は、私個人としてのアプリ情報なのか、WordPress.com全てで共通なそれなのか区別が付いていない。後者を配慮してユニークであろうアプリ名称にしておいたが。

  4. 4. 正直、これまでも、今も躊躇しているが「煩悩」タグな投稿が出てくる方が幾分マシな心境。