PubSubHubbubの使い方

公開日:
更新日:
0SEO

PubSubHubbub とは

PubSubHubbub (パブサブハブバブ) とは、更新情報を Google にリアルタイムで通知することができるプロトコルです。略して、PuSH (プッシュ) とも呼ばれます。Pub は Publisher (配信)、Sub は Subscriber (購読) を意味しており、その間に Hub というサービス (中間サーバ) があるため、このような名前になっています。配信側がコンテンツを更新すると、Hub が購読側に通知を行います。購読側は更新情報をすぐに知ることができるため、リアルタイムの情報配信が実現できる仕組みになっています。


ブログやニュースを Atom や RSS などで購読している場合、Atom や RSS リーダーは、一定間隔でコンテンツに更新情報がないかを問い合わせています。しかし、コンテンツが更新されても、次の問い合わせが行われるまでは購読側に更新されたことが通知されず、リアルタイムで更新情報を検知することができない問題点があります。


このプロトコルは、データフィードとして Atom や RSS を拡張した設計となっており、HTTP の通知を Push 技術を用いて行っています。これは、サーバ上のフィードに一定間隔でアクセスしなくても、Hub が更新情報を購読側に通知するため、リアルタイムで更新情報を得ることができます。また、HTTP 経由でアクセスできるデータであれば、どのようなデータ形式 (テキスト、画像、動画など)にも適用できます。PubSubHubbub の詳しい仕様は以下から確認できます。


PubSubHubbub Core 0.4 -- Working Draft

インデックスに登録されるスピードの重要性

Google は、検索結果に新しい情報を表示させるためにクローラーと呼ばれるロボットを世界中の Web ページに巡回させています。クローラーが収集したページをインデックスに登録してもらうには、クローラーにページを巡回してもらう必要があります。しかし、サイトの規模、知名度、更新頻度などにより、クローラーの巡回頻度はページによって異なります。検索エンジンの仕組みについては、Google 検索エンジン最適化手法を参照して下さい。


インデックスに登録されるスピードは重要です。コンテンツの鮮度はもちろん、他人の記事をスクレイピング (コピー) するスパムがいるため、オリジナル性の確保のためにもインデックスに登録されるスピードは重要になります。Google はオリジナル記事とコピー記事を見分ける要因の 1 つとして、コンテンツを発見した時間を評価しています。そのため、スクレイピングにより記事のオリジナル性が失われた場合、逆に Google から不当に低い評価を受ける場合があります。


コンテンツをインデックスに登録するためには、サイトマップや、Atom/RSSフィードを送る方法がありますが、Google ではスクレイピングに対抗するために、PubSubHubbub の利用を推奨しています。サイトマップや、Atom/RSSフィードを送る方法でもインデックスに登録はされますが、数分 ~ 数十分かかります。一方、PubSubHubbub は数秒以内で登録されるようです。

PubSubHubbub にリクエストを送る方法

PubSubHubbub にリクエストを送る場合は、下記の URL に POST でリクエストを送ります。


http://pubsubhubbub.appspot.com/

リクエストを送る場合、data として "hub.mode""publish" を設定し、"hub.url""フィードのURL" を設定します。また、"Content-Type" には "application/x-www-form-urlencoded" を設定します。以下は、Perl で実装した例です。実行結果として HTTP ステータス 204 (No Content:内容なし) が返れば成功です。ただし、成功してもインデックスされるかは Google 次第となります。


#!/usr/bin/perl

use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request::Common;
 
my $post = {
  url => 'http://pubsubhubbub.appspot.com/',
  data => {
    'hub.mode' => 'publish',
    'hub.url'  => 'https://murashun.jp/atom.xml'
  },
};

my $ua  = LWP::UserAgent->new();
my $req = POST($post->{url}, [$post->{data}]);
my $res = $ua->request($req);

print $res->as_string;

exit(1);
 PubSubHubbub で POST リクエストを送る例
HTTP/1.1 204 No Content
Cache-Control: no-cache
Connection: close
Date: Tue, 15 Sep 2015 11:24:49 GMT
Server: Google Frontend
Content-Length: 0
Content-Type: text/plain; charset=utf-8
Client-Date: Tue, 15 Sep 2015 11:24:49 GMT
Client-Peer: 74.125.204.141:80
Client-Response-Num: 1
 実行結果

上記のコマンドを実行すると、PubSubHubbub にリクエストを送りますが、更新する度にリクエストを送るのが面倒である場合は、CRON を使う方法もあります。例えば、CRON の起動時間から過去 n 秒 ~ 時間以内に更新のあったファイルは PubSubHubbub にリクエストを送るなどです。CRON による方法は、Atom/RSS のポーリング方式と基本的に変わらないため、リアルタイムのインデックスを実現させることはできません。しかし、インデックスされるまでの時間を大幅に短縮することができます。


フィードについては、Perl でフィード (Atom) を作成する方法を参照して下さい。

pubsubhubbub への送信を自動化する

CRON を使うことにより pubsubhubbub への送信が自動化できます。CRON とは、特定のコマンドを定期的に実行する機能で、さくらインターネットのレンタルサーバーでは "スタンダード" 以上のプランから利用できます。 ただし、CRON の設定や実行するプログラムによってはサーバーに負荷がかかり、サーバーを共有している他のユーザに影響を与える場合がありますので、利用には注意が必要です。 以下は、過去 10 分以内に更新のあったファイルを調べて、更新があればフィードを pubsubhubbub へ送信するプログラムです。


#!/usr/bin/perl

use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request::Common;

# 現在時刻算出 (過去 10 分以内)
my $date = time - 600;
($sec, $min, $hour, $mday, $mon, $year) = localtime( $date );
$date = sprintf("%04d%02d%02d%02d%02d%02d", $year + 1900, $mon + 1, $mday, $hour , $min , $sec);

# pubsubhubbub に送る対象のディレクトリを設定
search1('../../contents/');
search1('../../blog/');

# ディレクトリの中身を走査
sub search1 {
    opendir(DIR, $_[0]);
    my @filelist = readdir(DIR);
    closedir(DIR);
    foreach my $file (@filelist) {
        if ($file !~ /.+\.s?html$/) { next; }
        if (-d "$_[0]/$file") {
            &search1("$_[0]$file/");
        } else {
            &search2($_[0], $file);
        }
    }
}

# 対象ファイルの更新時間を取得
sub search2 {
    my ($sec, $min, $hour, $day, $mon, $year) 
          = localtime((stat $_[0] . $_[1])[9]);
    $year = $year + 1900;
    $mon  = sprintf("%02d",$mon + 1);
    $day  = sprintf("%02d",$day);
    $hour = sprintf("%02d",$hour);
    $min  = sprintf("%02d",$min);
    $sec  = sprintf("%02d",$sec);
    my $upd = $year . $mon . $day . $hour . $min . $sec;
    
    # 過去 10 分以内に更新があればフィードを pubsubhubbub に送る
    if($upd >= $date){
      &http_post();
    }
}

# pubsubhubbub に送信
sub http_post{
  my $post = {
    url  => 'http://pubsubhubbub.appspot.com/',
    data => {
      'hub.mode' => 'publish',
      'hub.url'  => 'https://murashun.jp/atom.xml'
    }
  };
  
  my $ua = LWP::UserAgent->new();
  my $req = POST($post->{url}, [$post->{data}]);
  my $res= $ua->request($req);
  
  exit(1);
}

exit(1);
 CRON を利用する pubsubhubbub の自動送信

CRON でプログラムを実行するには、パーミッションを "700(rwx------)" に設定します。そして、一般的には crontab コマンドで CRON の設定をしますが、さくらインターネットではサーバコントロールパネルで CRON を設定できますので、そちらで設定していきます。


左のメニューから "アプリケーションの設定" の中にある "CRONの設定" をクリックし、">> 新規項目の追加" を選択します。


CRON設定
CRON設定


"実行コマンド" に以下を設定します。コマンドパスや、ディレクトリパスなどは実行環境によって変更して下さい。


/usr/bin/perl /home/murashun/www/cgi-bin/pubsubhubbub.pl
 CRON の設定例

CRON の実行間隔は対象コンポーネントの量や更新頻度によって異なるため、サーバに負荷がかからない程度に設定して下さい。

まとめ

PubSubHubbub はインデックスへの即時登録と、それによるスクレイピングサイトへの対抗の 2 つのメリットがあります。大手ブログサイトでは標準で実装されていたり、プラグインが用意されているため簡単に対応できるはずです。個人サイトは、それらのブログサイトに比べて難しいですが、挑戦してみる価値はあります。