Word of the Day を自作しよう

Takayuki Kawamoto

Contact: takayuki.kawamoto [at] gmail.com

ORCID iD iconorcid.org/0000-0002-7867-2654, Google Scholar

First appeared: 2018-04-24 16:49:11,
Modified: [BLANK],
Last modified: [BLANK].

はじめに

Wikipedia でも、なぜかちゃんとした説明が整備されていないのですが、多くの方がご存知のように、毎日単語を一つずつ(たいていは何らかの方法で無作為に)選んで、簡単な定義などを一緒に掲載するものを “Word of the Day” と言っています(なお、“WOTD” という略語があるらしいのですが、頻繁に使われている印象は全くないので、本稿では使いません)。

Word of the Day

さて、僕は何日か前に「ホームページ」(ブラウザが起動したときに表示される「スタートページ」のこと。本来はウェブサイトの意味ではない)を 作り直しました。そのページで使っている Bootstrap というフロントエンドのライブラリがバージョン 4.1 にアップデートしていたので、運用知識もアップデートするついでにホームページを作り直したわけです。その際に、 空いた領域に Word of the Day の単語を表示してみようと思ったのですが、調べてみると “Word of the Day” と称して提供されているコンテンツ(ウェブページ、RSS、アプリケーション等)は数多くの種類があります。そこで、手軽にページの要素として埋め込んで表示するための手順をまとめてご紹介することにしました。

但し、“Word of the Day” の単語データは色々な形式や配信方法があるため、幾つかの条件で一部だけに対応しています。まず、単語データを無料で入手したり表示できること。利用するにあたって費用を出せるなら、アプリケーションを購入すれば済みますし、サイトで表示するためのプログラムも他人に発注することすら可能ですから、こういうページを見る必要などないでしょう。

また、このような単語を無作為に表示する機能を何のために使うのかという点でも、一定の条件や目的や事情を考慮する必要があります。本稿では、このような機能を使って表示される単語を習得したいと思っている人を対象にします。漫然と、興味のない単語を表示させて何かの自意識プレイをしたいというていどの動機で単語を画面に表示しても構いませんが、そんなことをしていても何の意味もないということだけは弁えておく必要があります。

次に、単語データを入手するにあたって、個人情報や利用サイトなどの情報を提供する「ユーザ登録」とか「アプリケーション登録」が必要ないことです。僕が自分で実装しているのは、あくまでも僕のコンピュータというローカル環境でブラウザに表示するページですから、API を利用するウェブサイトを登録せよと言われても困りますし、ましてや個人情報を提供するようなことでもないと考えます(データを利用させてもらうのですから、もちろん何かとの「バーター」であってもかまいません。その取引関係そのものが不当だと言いたいわけではないのです)。

それから開発・実装環境としては、Apache などのウェブサーバ・アプリケーションをローカル・コンピュータで動かしていることと、PHP を使うことです。ブラウザでローカル・コンピュータのページを表示するだけならウェブサーバは必要ありませんが、今回は PHP を使っているので、ウェブサーバの運用も前提に入れておきます。PHP は、大量のデータファイルを整形して保存するところまで使って、ウェブページに単語を表示するところは JavaScript に任せてもよいのですが、JavaScript でメモリにロードした大量の(表示内容とは関係のない)データが滞留してしまうのは良くないので、最終の表示まで PHP で書いています(HTML 内で PHP の処理を埋め込みたいので、AddType application/x-httpd-phpで HTML ファイルを PHP のパーサに通す指定を追加してください)。データの数が少なければ、JavaScript でファイルのデータを読み込んで、ランダムに単語を表示してもいいと思います。

そして最後に、Word of the Day の単語は、ローカル・コンピュータに保存してあるデータファイルを元に表示します。このような設計にする理由は幾つかありますが、まず API のようなもので提供元サイトへアクセスする場合は、アクセスできる回数に制限があるため、社内でこのようなページを共有している場合にはアクセス回数の制限を越えてしまう可能性があるからです(たいていは1日に数千回といった制限で、これは多いように見えるかもしれませんが、僕のようにブラウザの起動と終了を頻繁にやる人のマシンなら、だいたい1日に百回近くの回数になります。接続元の IP アドレスを共有している、数十人規模の事業所で同じようにやっていれば、数千回の制限は考慮しておかないといけない数字です)。

冒頭に戻る

単語データを用意する

では、単語データを集めます。ローカル・コンピュータに単語データを置いて使えることが要件だったので、これは無料で使えるデータを探しましょう。Oxford University Press, Cambridge University Press, Merriam-Webster, Longman, HarperCollins, Macmillan といった辞書の主な出版社は単語のデータファイルを提供などしていませんし、辞書に付属しているメディアからテキストデータを抽出して使うのは利用規約違反ですから、やめましょう。もちろん、僕は情報セキュリティの実務家なので、いわゆる「辞書引き攻撃」用のデータなるものが出回っていることも知っていますが、そういうデータの出自が何であるかは重要です。それらが、いま述べたような利用規約違反の利用方法で集めたデータから出来上がっているなら、もちろんそれを使うべきではないでしょう。

著作権を気にせず利用できるデータとしては、“Moby Word Lists” (Grady Ward, 2002-05-01, Public domain in the USA) があります。また UNIX/Linux ユーザであれば、/usr/share/dict/words というファイルが単語リストになっていることもご存知でしょう。その他、著作権の切れた類語辞典(シソーラス)から単語を個人で抽出している人もいます。いずれにしても、その単語データ(もちろん単語そのものに著作権はありません)の作成や抽出方法に法的・道義的な問題がないかどうかを確認しておくべきです。たとえローカル・コンピュータでプライベートに利用するとは言っても、違法なものは違法です。

それから、これは辞書や学習用の英単語集などを選ぶときにも言えることですが、やたらと単語の数だけに拘るのは愚かです。200,000 words のリストは 50,000 words のリストよりも収録している単語の数は多いでしょう。しかし、このような膨大なリストから無作為に単語を抽出しているのですから、元のデータが巨大になればなるほど、或る単語が或る機会に表示される確率は下がってゆき、結局のところ死ぬまでに一度もお目にかかれない膨大なデータのためにローカル・コンピュータの能力を無駄に使うことになります。“Word of the Day” で表示される単語は、しょせん埋め草ていどのものでしかありませんが、機会と能力があれば可能な限り心に留めておきたいものです(そういう興味がないなら、そもそも “Word of the Day” など表示しても埋め草の役にすら立ちません)。したがって、よほど奇怪な、アメリカで英米文学を専攻しているわけでもないなら大学教授ですら知らないような単語を表示したいというならともかく、ごくありふれた単語を表示して役立てたいというのであれば、むやみに膨大な単語データを使うのは馬鹿げています。例えば “larum” とか “sigmoidoproctostomy” なんていう単語を表示するのは楽しいかもしれませんが、たいていの人はこんな単語を覚えるよりも先に学ぶことがある筈です(ちなみに “larum” は大昔の綴りの “alarm” で、“sigmoidoproctostomy” は「S状結腸直腸吻合術」という医学用語です)。

冒頭に戻る

データの整形と最適化

ということで、ここでは Moby Word Lists を選びます。データを ZIP ファイルとしてダウンロードすると、アーカイブには幾つかのファイルが入っていることが分かります。それぞれのファイルの目的は、Wikipedia に説明があります。この中で、本稿では “COMMON.TXT” というデータ・ファイルを単語リストとして使います。理由は、複数の異なる辞書に掲載されている頻出語が含まれているからです。僕がダウンロードした COMMON.TXT は 74,550 行、つまり 74,550 個の単語が収録されています。ただ、そのままだと “a” や “the” のような単語も含まれているので、データを整形・最適化します。もちろん、それらの単語を知らなくてもいいという主旨ではなく、それらは “Word of the Day” で偶然に表示されるのを待ってから学習するような単語ではないという主旨で除外します。

他のデータ・ファイルにも言えることですが、たいていのデータ・ファイルは特定の目的のために規格化され、独特のフォーマットになっていたりします。もとのフォーマットがあまりにも複雑で、そこから単語を取り出すための正規表現が難しくなるようだと、そこで無駄な時間を使うことになってしまいますから、できるだけ単純に、単語だけを1行に一つずつ記載してあるデータ・ファイルが望ましいと言えるでしょう(無料で使える単語リストとして、Princeton University の WordNet を除外したのは、ファイルのフォーマットが複雑すぎて、再利用する方法を調べるだけでも手間がかかるからです)。理想的なのは /usr/share/dict/words ファイルのように単純なフォーマットです。

では、かなり雑ですが、データ・ファイルを次のような方針で整形・最適化します。(1) 固有名詞や地名など大文字で始まる単語を除外する。(2) ピリオドやアンパーサンド等の記号を使った略語や複合語を除外する。これらの方針で、COMMON.TXT を整形し直すコードを以下のように PHP で書いて実行します。具体的には、Apache でアクセス可能な作業用のディレクトリを作って(例えば “http://challenge.localhost/”)、ホームディレクトリの直下に /COMMON.TXT と /index.php を置いて、/index.php には以下のようなコードを書きます。

<?php $data = file( './COMMON.TXT' ); $fp = fopen( './result.txt', "a" ); flock( $fp, LOCK_EX ); foreach( $data as $word ) { if ( preg_match( "/^[a-z].*\n/", $word ) AND ! preg_match( "/^.*(\.|\&|\'|\-)+.*\n/", $word ) ) { fputs( $fp, $word ); } } flock( $fp, LOCK_UN ); fclose( $fp );

以上の処理で、もともと 74,550 行あった単語が 57,756 行に減ります。6万弱の単語数だと、せいぜい中型の辞書が収録するくらいの分量になりますが、この数の単語リストについて「あれがない、この単語がどうした」と言えるほどの語彙がある人なら、そもそも Word of the Day など不要でしょう。

冒頭に戻る

ページに表示する

最後に、この単語リストをもとにして、ホームページに単語を無作為に選んで表示します。表示する HTML 要素は、Bootstrap を使っているという前提で、<div /> 要素に入れます。更に、表示した単語をクリックすると新規ウィンドウで辞書のサイトを表示しましょう。こうすると、そのまま語義を確認できます。リンクする辞書サイトは幾つかありますが、僕がお勧めするのは Merriam-Webster のサイトです。Cambridge University の辞書サイトなどは、収録されている単語と正確に一致していない単語を検索した場合は、単語を選択する画面が出てくるか無視されてしまいますが、Merriam-Webster の辞書サイトは綴りの近い単語をかなり正確に見つけて語義を表示してくれます。こういう手軽な機能で、いちいち単語を選ぶなんて手間はかけていられません。もちろん、綴りが似ているだけで語源や意味の違う単語を表示されてしまうと、派生語を間違って覚えてしまうというリスクはありますが、いまのところそういう間違いはなく、かなり高性能な判定をしてくれていると思います(もちろん、そもそも辞書のデータベースに存在しない単語や類推できなかった単語は選択画面になりますが)。

ということで、整形した result.txt を使って、ページに表示する単語を選び出して、Merriam-Webster のサイトへリンクを付けてみます。まず、単語を無作為に選び出します。

<?php $words = file( './result.txt' ); $pos = mt_rand( 0, count( $words ) ); $word = preg_replace( "/\s/", "", trim( $words[ $pos ] ) );

選んだ単語を格納している $word という変数を使って、

<a target="_blank" class="text-white" href="https://www.merriam-webster.com/dictionary/<?php echo $word; ?>"><?php echo $word; ?></a>

というようにアンカーを埋め込んで、単語を表示する箇所のスタイルシートを調整して下さい。出来上がりは下記のようになります。

Word of the Day

冒頭に戻る


※ 以下の SNS 共有ボタンは JavaScript を使っておらず、ボタンを押すまでは SNS サイトと全く通信しません。

Google+ Twitter Facebook