dtn.jpトップページのニュース表示

ディレクトリ型検索エンジンdtnのトップページでは、YahooやMSNやライブドアといった大手ポータルサイトと同じように新着ニュースをトップに表示させています。ポータルサイトっぽさを出すにはニュース表示が必要だろうということで、dtn.jpを作った当初からニュースをトップページに表示してありました。

かつてはYahooトピックスAPIで表示

2007年頃はYahooのAPIでニューストピックスAPIといったものが提供されており、Yahoo Japanのトップページに表示されているニューストピックスデータと同じデータをAPI経由で取得することができました。今考えるとかなりの大盤振る舞いサービスだったようです。

APIサービス終了後はRSSデータで表示

APIブームの終了に伴い、YahooトピックスAPIもサービス終了となってしまいましたので、とりあえずは某ニュースRSSのデータを使ってトピックスを表示させておりましたが、RSSの二次利用はかなりグレーな問題もありますので、他に使えそうなAPIをずっと探してはおりました。

・提供するRSSは個人利用にのみ使用することができます。
RSSから取得した情報を用いたウェブサイトやアプリケーションなどのプログラムを作成して公開することは許可しておりません。また、RSSの再配信や再提供も許可しておりません。

YahooのRSSの利用マニュアル

ニュース記事配信APIを探してはいたものの、このご時世ではなかなか無料で使える良さげなサービスが見つからず、時間もないのでそのままにしてしまっておりましたが、ふとしたタイミングで最適なニュースAPIを見つけることができました。

Bing APIにニュース取得用のAPIを発見

それが「Bing News Search API」でした。

これまでYahoo、Google、TwitterとAPIは色々使ってきたものの、MicrosoftのAPIを使ったという話も聞いたことがなかったため意外な盲点でしたが、Bing Search API では検索エンジンbingで提供している検索データや、画像検索、ニュース検索など、様々なサービスをAPIで提供しているようです。

Bing News Search API lets your users find headline news, news by category, and trending articles. If you’re looking to build an experience similar to bing.com/news, this is the API to use.

What is the Bing News Search API?の説明

ただし、私の世間知らずが原因か、はたまたマイクロソフトのAPI知名度があまり高くないことが原因かはよくわかりませんが、ドキュメントは英語のものしか見当たらず、Bing APIに関するネットの記事もあまり見当たらないので少々微妙でしたが、使ってみるとMicrosoftが提供するサービスなのでレスポンスは非常によく、しかも無料で利用することもできましたので、かなり使えるサービスということが今更ながらよく分かりました。

なお、完全無料で使えるというわけではなく、有料サービスが基本なものの、TPSとトランザクション数を抑えれば無料で利用が可能といった意味ですので、このあたりはご注意下さい。

インスタンス1 秒あたりのトランザクション数 (TPS)機能料金
無料3 TPSBing Image Search
Bing News Search
Bing Video Search
Bing Visual Search
Bing Web Search
1,000 無料トランザクション / 月

Microsoft Azureアカウントが必要

Bing APIを利用するためには「Microsoft Azure」のアカウントを取得する必要があります。

Microsoft Azureは2010年頃にサービスを開始したクラウドサービスの総称のことで、Amazon AWSと同じようなクラウドプラットフォームの従量課金型サービスといったものになりますが、Bing Search API利用にあたり、このAzureアカウント登録が必須のようですので早速登録をしてみました。

Azureアカウントの取得

こちらの「Microsoft Azure」の申込画面から「無料で始める」ボタンに進みます。

Microsoft Azureの登録画面からアカウント作成できます。

個人情報の登録

国/地域、氏名とメールアドレス、電話番号を登録します。電話番号は後々SMS認証に利用するので携帯番号が良さそうです。

個人情報の登録

SMSによる個人認証

先ほど登録した携帯番号にSMS認証の確認コードを送信させます。

SMSによる個人認証

クレジットカードによる本人確認

クレジットカードを登録して本人確認をさせます。アップグレードや制限以上の利用がなければ課金されるはないとのことですが、何かやらかした場合にはこのカードから請求されることになるようです。

クレジットカードによる本人確認

最終同意

電話による本人認証、クレジットカードによる本人確認が終了すれば、最終同意画面が表示されます。

サービスの最終同意画面

Azureアカウント作成完了

これでAzureアカウントの取得が完了したのでポータルに移動します。

Azureの利用開始準備ができました

Bing Search API v7

Azureのポータル画面にログインすると、さまざまなAzureサービスが一覧で確認することができます。Azure SQLや仮想マシンなど、IaaS/PaaSのクラウドサービスが100以上ずらっと並んでいます。全部使ったらかなり面白いことができそうですが、貧乏人には課金が恐ろしいので特に触らず目的のブツを探します。

Azureのサービス一覧

今回やりたいことはニュースAPIでニュースを取るだけですので、「Bing News Search API」が含まれた「Bing Search API v7 」という名のAPIを探します。検索窓で「bing」と検索して探してしまいましょう。

Bing Search v7がありました

F1サブスクリプション

みつけた「Bing Search API v7 」に進むと「Bing リソース」の作成に進みます。適当にリソースの名前を付けて、価格レベルをF1サブスクリプションにしておけば課金はひとまず避けられるようです。

Bingリソースの作成

APIキーとエンドポイント

ポータルに「Bingリソース」が無事追加ができたらやっと準備完了です。ここまできたら「キーとエンドポイント」を画面で確認することができますので、あとはプログラムを書けばOKです。

豊富なドキュメントとサンプルコード

マイクロソフトのサービスということもありドキュメントはかなり充実していました。英語マニュアルしか見当たりませんでしたが、QuickStartにC#、Java、Node.js、PHPといった各言語のサンプルまでご用意してくれてあるので、それを元にすれば問題なさそうです。

PHPのサンプルコードはこんな感じでした。

<?php

// NOTE: Be sure to uncomment the following line in your php.ini file.
// ;extension=php_openssl.dll

// **********************************************
// *** Update or verify the following values. ***
// **********************************************

// Replace the accessKey string value with your valid access key.
$accessKey = 'ここにAPIキーを設定';

$endpoint = 'ここにエンドポイントを設定';

$term = 'Microsoft';

function BingNewsSearch ($url, $key, $query) {
    // Prepare HTTP request
    // NOTE: Use the key 'http' even if you are making an HTTPS request. See:
    // https://php.net/manual/en/function.stream-context-create.php
    $headers = "Ocp-Apim-Subscription-Key: $key\r\n";
    $options = array ('http' => array (
                          'header' => $headers,
                          'method' => 'GET' ));

    // Perform the Web request and get the JSON response
    $context = stream_context_create($options);
    $result = file_get_contents($url . "?q=" . urlencode($query), false, $context);

    // Extract Bing HTTP headers
    $headers = array();
    foreach ($http_response_header as $k => $v) {
        $h = explode(":", $v, 2);
        if (isset($h[1]))
            if (preg_match("/^BingAPIs-/", $h[0]) || preg_match("/^X-MSEdge-/", $h[0]))
                $headers[trim($h[0])] = trim($h[1]);
    }

    return array($headers, $result);
}

print "Searching news for: " . $term . "\n";

list($headers, $json) = BingNewsSearch($endpoint, $accessKey, $term);

print "\nRelevant Headers:\n\n";
foreach ($headers as $k => $v) {
    print $k . ": " . $v . "\n";
}

print "\nJSON Response:\n\n";
echo json_encode(json_decode($json), JSON_PRETTY_PRINT);
?>

カテゴリ別のニュース取得

マニュアルをみていくと、クエリストリングにパラメータmktとcategory情報を付与して投げれば、カテゴリ別にニュース情報を取得できるようでした。

https://api.bing.microsoft.com/v7.0/news?mkt=en-us&category=sports

カテゴリはマーケット別に異なるようで、マーケット別カテゴリ一覧を見ると日本地域ではこのような分類がされておりました。

Japan (ja-P)
・Business
・Entertainment
・Japan
・LifeStyle
・Politics
・ScienceAndTechnology
・Sports
・World

マーケット別のニュースカテゴリ一覧

もともとdtn.jpのトップページで表示していたニュースは、国内・海外・経済・エンタメ…といった形でタブ分けをしてニュースを表示していたので、カテゴリ別にニュースが取得できればそっくり今の形にはめ込みができそうです。早速試してみました。

連続したAPIクエリ送信にはご注意を

先ほど見つけたマーケット:Japan (ja-P)のカテゴリを配列に設定し、接続先エンドポイントにカテゴリを順々に付けて取得してみたところ、全く問題なくニュースをカテゴリ別に取得することができました。

APIの連続送信で課金が発生!?

テスト送信を何度かやってデータ取得が問題なくできることを確認したところまではよかったのですが、Azureのポータルを見ていると無料枠にもかかわらず請求が発生してしまっておりました。

152.55円の課金が!?

月間1000トランザクションまでは無料のはずで、さすがにこの短時間に1000回も回しているわけはありませんので、どうやら1秒当たりのトランザクション3TPS以内というところを超えたということのようです。

先程ご紹介したマーケット:Japan (ja-P)のカテゴリは8カテゴリですので、これを配列でぶん回して何も考えずに取りに行っていたので、3TPSは確実に超えてしまっていたようです。

やってしまったものはどうしようもなさそうですので、カテゴリの問い合わせをするごとにsleep()で1秒止めてデータ順次取得するようしておきました。sleep()でお眠りさせてからは課金されずに済みましたが、152.55円取られたのがなんだか悲しかったです。

sleep(1);

サイトに無事ニュースが表示

無料枠に収めるためには、月間1000トランザクション以内にする必要があるので、API接続は1時間に1トラン程度で済むようにバッチ処理化をしました。

cronで取得したニュースデータは一旦DBにためておき、トップページではDBデータを表示するようしてあります。ニュース情報がリアルタイム更新されたものとはできませんでしたが、これでサイトトップにニュースが表示できるようになりました。

カテゴリ別の新着ニュースを表示ができました

取得したJSONのレスポンスにはニュース記事毎に画像も設定されておりましたので、画像を記事横に表示させることができればよりポータルサイトっぽくできそうです。時間があったら差し込んでみたいと思います。

ニュース情報が取得できていない

無事サイトに表示されたので安心しきっておりましたが、大晦日にサイトトップをみていたところ、ニュース情報が数日前と変わっていないことに気が付きました。

急いでDBのテーブルを確認してみたところ、12月22日頃のニュース取得が最終となっており、どうやらそれ以降はニュース情報を取得することができていなかったようです。

直接APIにリクエストを投げてみると「403 Quota Exceeded api error」が返ってきておりまして、なにやら回数制限を受けているような印象です。

ヘルプを見ても原因がよく分からず、仕方ないのでリソースを一度消して再度同じ名前で作り直し、新しいAPIキーで接続をしてみたところすんなり接続ができてしまいました。

APIキーの有効期限

「F1 Free」の無料利用だからかもしれないですが、APIキーを一定期間経過後に再生成をかけないと動かなくなる仕様ということのようです。

DBに残っていたログをみていると12月22日の0時00分までは取得ができていたようです。API側のログでは、12月14日からこのキーを使い始めていたようなので、ちょうど7日間でAPIキーの有効期限が切れるということのようです。

APIキーの再生成ボタンがある

Azureポータルの「Bing Search」リソースを見ると、「Key1の再生成」「Key2の再生成」というボタンが置いてあるので、こいつで一週間に一回は更新しろということかもしれません。

キーの再生成というボタンが……

おわりに

APIキーの有効期限は7日間といった厄介な仕様ということが分かりましたが、そこさえ我慢すればマイクロソフトが提供する、レスポンスに機能も最高のAPIを無料で利用ができるので、今のご時世ではかなりの大盤振る舞いAPIといっても良いとは思います。よければお試ししてみて下さい。