このページの本文へ

LPO導入で用語辞典からASCII.jpへの誘導が2倍に! (3/4)

2008年11月28日 08時00分更新

文●中野克平/デジタルコンテンツ部編成課/技術部基盤研究課

  • この記事をはてなブックマークに追加
本文印刷

1.リファラーの取得と解析

 ユーザーがどのページから現在のWebページに到達したのかを取得するには、Webブラウザー内のJavaScriptプログラムでリファラーを取得してWebサーバーに伝える方法(「Ajax方式」と名付けよう)と、Webサーバー側でリファラー情報を取得する方法(「CGI方式」と名付けよう)がある。

 Ajax方式では、DOMを使ってWebページ内に動的に関連記事を埋め込めるので、静的HTMLのWebページでも実現できるメリットがある。だが、Webブラウザー側のJavaScriptプログラムとは別に、送信されたリファラーをWebサーバー側で受信する機能も必要であり、開発がやや面倒である。

 一方、CGI方式では、Webサーバーでリファラーを読み取る。PHPなど、サーバー側で動作するスクリプト言語を使えば、リファラーを取得して関連記事を表示する機能を、Webページのテンプレートなどに埋め込むだけ済むため、開発が容易である。しかし、Webページの生成ごとにリファラーを取得し、キーワードを解析して関連記事をデータベースで検索することになるから、Webサーバーの負担が重くなる。

 今回LPO機能を追加する用語辞典は、MediaWikiで動作している。MediaWikiはオンライン百科事典Wikipedia用のCMSで、Wikipediaも用語辞典も、負荷低減のためにMediaWikiとキャッシュサーバーを組み合わせて、処理の大半を省略している。用語辞典にLPOを付加するとき、CGI方式では動的に関連記事を生成する処理が新たに増え、しかもユーザーごとにページの内容が異なればキャッシュサーバーの出番が無くなる。Webページのうち、更新頻度の低い用語部分だけキャッシュする方法もあるが、今回はキャッシュサーバーの役割を変えずに済むAjax方式で開発することにした。

function getSearchString()
{
var g_pattern = /\?q=|&q=([^&]+)/;
var y_pattern = /p=([^&]+)/;
var ret = document.referrer.match(g_pattern);
if (ret) {
return ret[1];
}
ret = document.referrer.match(y_pattern)
if (ret){
return ret[1];
} 
return null;
} 
function serach(transport)
{
if ("" != transport.responseText) {
document.getElementById('articles').innerHTML =  transport.responseText;
document.getElementById('articles_header').innerHTML = S_HEADER + g_reqWords.replace(/\+/g,' ') + FOOTER;
} else {
req = 'q=' + encodeURIComponent(toXml(Array(decodeURIComponent(g_title)),Array()));
g_reqWords = decodeURIComponent(g_title);
myAjaxRequest(URL,req,midashi);
}
}
function myAjaxRequest(url,param,func)
{
new Ajax.Request(url, {
method:'get',
parameters: param,
onSuccess: func
}); 
}

Ajax方式で作ったLPOのJavaScriptプログラムの一部(全体はhttp://yougo.ascii.jp/articles/articles.jsでダウンロードできます)。「document.referrer」でWebブラウザーがWebサーバーに送信したリファラーを取得し、Googleなどの検索エンジンのリファラーであれば検索語を取り出してAjaxでサーバーに関連記事を問い合わせる仕組みです



2.関連記事のデータベース化

 検索語を含む関連記事を取得するには、ASCII.jpの記事を全文検索するためのデータベースが必要だ。しかしASCII.jpと用語辞典が動作するサーバーは別なので、ASCII.jpの最新記事を以下のようなXMLではき出すプログラムを用意し、用語辞典側サーバーで専用のデータベースに格納、検索できるようにした。

<CMSjpArticleAttributes>
<Build>Mon, 24 Nov 2008 15:03:16 +0900</Build>
<Version>1.0</Version>
<Site URL="http://ascii.jp/">ASCII.jp</Site>
<Articles>
<Article>
<EID>176173</EID>
<RegisterDate>Wed, 01 Oct 2008 01:44:52 +0900</RegisterDate>
<UpdateDate>Mon, 24 Nov 2008 02:43:54 +0900</UpdateDate>
<Editors>
<Editor ID="1004" Action="Register">廣田 稔</Editor>
<Editor ID="1004" Action="Update">廣田 稔</Editor>
</Editors>
<Categories>
<Category ID="13" Main="Yes">ネット</Category>
</Categories>
<Images>
<Image Class="Representative">
http://ascii.jp/elem/000/000/176/176201/000_90x90.jpg
</Image>
<Image Class="Thumbnail">
http://ascii.jp/elem/000/000/176/176201/000_40x40.jpg
</Image>
</Images>
<Attributes>
<Title>「こ、孔明の罠!」 ニコニコ動画(秋)の発表会に行ってきた</Title>
<SubTitle>気になる新機能を画像でチェック</SubTitle>
<Priority Level="0">通常</Priority>
<Restriction Level="-1">一般公開</Restriction>
<PublishBeginDate>Wed, 01 Oct 2008 09:44:12 +0900</PublishBeginDate>
<URL>http://ascii.jp/elem/000/000/176/176173/</URL>
<Summary>ドワンゴから、9月30日に新バージョンの発表会である「ニコニコ小会議」を開くという知らせが届いた。これはぜひ行かなければと会場に向かったところ……</Summary>
</Attributes>
<RelatedArticles>
<RelatedArticle>
<EID>148335</EID>
<Attributes>
<Title>「ひろゆき」のブロマイドを入手した</Title>
<URL>http://ascii.jp/elem/000/000/148/148335/</URL>
</Attributes>
</RelatedArticle>
<RelatedArticle>~略~</RelatedArticle>
</RelatedArticles>
</Article>
</Articles>
</CMSjpArticleAttributes>

将来的に記事配信のWeb APIを一般公開することも検討しており、XMLで記事情報を生成するプログラムを用意しました


3.関連記事の検索とHTML化

 用語辞典が利用しているデータベースサーバーはMySQL+Sennaで日本語の全文検索が可能であり、用語辞典LPOでは、以下のようなSQLで該当する記事を抽出している。

SELECT `Title`,`Url` FROM `article` WHERE MATCH (`Title`,`SubTitle`,`Summary`) AGAINST ('<検索語>' IN BOOLEAN MODE) LIMIT <検索上限>;


 こうして抽出した関連記事は、以下のようなPHPプログラムでHTMLとして出力している。

function printHtml($list)
{
print '<h2><span id="articles_header" class="mw-headline"></span></h2>';
print '<ul>';
foreach ( $list as $elem) {
print '<li><a href="' . $elem['Url'] . '" title="' . $elem['Title'] . '">' . $elem['Title'] . '</a></li>';
}
print '</ul>';
}

どうということのないPHPプログラムですが、さすがに毎秒数十~数百回のクエリーが実行されるとなると、サーバーの負荷が心配。MySQLとSennaの組み合わせは非常に高速な全文検索システムですが、用語辞典LPOではキャッシュサーバーにより、関連記事HTMLを一定時間キャッシュすることで、負荷を低減しています。


 キャッシュサーバーは、見出し語または検索語ごとに、関連記事のHTMLファイル(画面全体ではなく、関連記事部分のみ)を保持している。JavaScriptプログラムで、検索エンジン経由の場合は「検索語『○○○』の関連記事」、それ以外の場合は「見出し語『○○』の関連記事」と表示を切り替えている。

 なお、先ほど説明したとおり、用語辞典はMediaWikiを利用している。JavaScriptプログラムはMediaWikiの標準テンプレートであるmonobook.phpを改造して埋め込んだ。

用語辞典のLPO対策

「Windows」を検索エンジンで検索し、ASCII.jpデジタル用語辞典に来訪したユーザーには「検索語『Windows』の関連記事」と表示されます


次ページ:LPOでASCII.jpへの誘導を2倍に!

Web Professionalトップへ

この記事の編集者は以下の記事をオススメしています