PHPで2つの文章の類似度を計算する(gooラボ版)

(1/1)
PHPで2つの文章の類似度を計算する」「PHPで2つの文章の類似度を計算する(KAKASI版)」「PHPで2つの文章の類似度を計算する(MeCab版)」「PHPで2つの文章の類似度を計算する(WebAPI版)」で、PHPの組み込み関数  similar_text  や N-gram、「KAKASI」による形態素解析を利用して、異なる2つの文章の類似度を計算する方法を紹介した。
今回は、gooラボが提供するWebAPI「テキストペア類似度API」を利用し、2つの文章の類似度を計算プログラムを作ってみることにする。

(2022年2月12日)PHP8対応,リファラ・チェック改良

目次

実行例

PHPで2つの文章の類似度を計算する(gooラボ版)

サンプル・プログラム

圧縮ファイルの内容
TextPairSimilarity.phpサンプル・プログラム本体

準備:各種初期値

0033: //表示幅(ピクセル)
0034: define('WIDTH', 600);
0035: 
0036: //gooラボ アプリケーションID
0037: //https://labs.goo.ne.jp/apiregister/ にて登録のこと.
0038: define('GOOLABS_APPLICATION_ID', '***************************************');
0039: 
0040: //初期値
0041: define('DEF_TEXT1',  '東京都内で新型コロナ・ウイルスの感染が拡大している。');
0042: define('DEF_TEXT2',  '東京都は新型コロナ・ウイルスの感染者を新たに65人以上確認した。');
0043: 
0044: //gooラボ リクエストURL
0045: define('GOOLABS_TEXTPAIR_URL', 'https://labs.goo.ne.jp/api/textpair');

gooラボが提供するWebAPIを利用するために、アプリケーションIDを入手する必要がある(無料)。入手手順は「各種WebAPIの登録方法 - gooラボ」を参照のこと。
取得したアプリケーションIDは、定数 GOOLABS_APPLICATION_ID に格納する。

その他の定数は自由に変更可能である。

gooラボ:テキストペア類似度API]

gooラボ:テキストペア類似度API」は、入力パラメータ(IN)としてJSON形式のデータをPOSTで渡し、出力結果(OUT)が JSONで戻るというAPIである。
WebAPIのURL
URL
https://labs.goo.ne.jp/api/textpair

入力パラメータ(JSON)
フィールド名 要否 内  容
app_id 必須 アプリケーションID
入手手順は各種WebAPIの登録方法 - gooラボ。無料。
request_id 任意 リクエストID
省略時は”labs.goo.ne.jp[タブ文字]リクエスト受付時刻[タブ文字]連番”となる。
text1 必須 1つ目の比較対象テキスト。UTF-8エンコード。
text2 必須 2つ目の比較対象テキスト。UTF-8エンコード。
応答データ構造(json) request_id リクエストと同じ値 score テキストペア類似度
score(テキストペア類似度)は、0.0から1.0の範囲の小数で、0に近いほど類似度が低く、1に近いほど類似度が高い。ただし、単純比例では無いため、注意が必要。概ね0.6以上の数値である場合、類似度が高いと言える。

解説:JSON形式データをPOST渡し

0180: /**
0181:  * JSON形式データをPOST渡し
0182:  * @param   string $urlリクエストURL
0183:  * @param   array  $data POST変数を格納した連想配列("変数名"=>"値") 
0184:  * @return  string取得したコンテンツ/FALSE取得エラー
0185: */
0186: function post($url$data = array()) {
0187:     //JSON化
0188:     $data_json = json_encode($data);
0189: 
0190:     //cURL送信
0191:     $curl = curl_init();
0192:     curl_setopt($curlCURLOPT_URL , $url);
0193:     curl_setopt($curlCURLOPT_HEADER, 1) ; 
0194:     curl_setopt($curlCURLOPT_POSTTRUE);
0195:     curl_setopt($curlCURLOPT_RETURNTRANSFERTRUE);    //結果を文字列で
0196:     curl_setopt($curlCURLOPT_POSTFIELDS$data_json);
0197:     curl_setopt($curlCURLOPT_SSL_VERIFYPEERFALSE);
0198:     curl_setopt($curlCURLOPT_SSL_VERIFYHOSTFALSE);
0199:     curl_setopt($curlCURLOPT_RETURNTRANSFERTRUE);
0200:     curl_setopt($curlCURLOPT_TIMEOUT, 5);
0201:     $res1 = @curl_exec($curl);
0202:     $res2 = @curl_getinfo($curl);
0203:     curl_close($curl);
0204: 
0205:     //結果処理
0206:     if ($res1 != FALSE) {
0207:         $json = substr($res1$res2['header_size']);
0208:     } else {
0209:         $json = FALSE;
0210:     }
0211: 
0212:     return $json;
0213: }

gooラボ:テキストペア類似度API」へデータを渡すために、ユーザー関数 post を用意した。
cURL関数群と、 json_encode  を利用することで実現している。
APIからの応答結果を、JSONテキストでリターンする。

解説:テキストペア類似度API呼び出し

0215: /**
0216:  * 「gooラボ テキストペア類似度API」を用いてテキストを比較する
0217:  * @param   string $text1, $text2比較するテキスト
0218:  * @param   string $errmsg        エラー・メッセージ格納用
0219:  * @return  intテキストペア類似度(0.0~1.0):1に近いほど類似度が高い
0220: */
0221: function getTextPairSimilarity($text1$text2, &$errmsg) {
0222:     //WebAPIにパラメータをPOST渡しする
0223:     $url = GOOLABS_TEXTPAIR_URL;
0224:     $post = array(
0225:         'app_id' => GOOLABS_APPLICATION_ID,
0226:         'text1'  => $text1,
0227:         'text2'  => $text2,
0228:     );
0229:     $score = FALSE;
0230:     $errmsg = '';
0231: 
0232:     //バージョンチェック
0233:     if (isphp5over() == FALSE) {
0234:         $errmsg = 'PHP4以下では動作しない';
0235:     } else {
0236:         //API呼び出し
0237:         $json = post($url$post);
0238:         if ($json == FALSE) {
0239:             $errmsg = 'WebAPIが停止';
0240:         } else {
0241:             $obj = @json_decode($json);
0242:             if (isset($obj->score))      $score = (float)$obj->score;
0243:             else                        $errmsg = 'WebAPIでトラブル発生';
0244:         }
0245:     }
0246: 
0247:     return $score;
0248: }

gooラボ:テキストペア類似度API」を呼び出すために、ユーザー関数 getTextPairSimilarity を用意した。

テキスト比較の実行例

PHPで2つの文章の類似度を計算する(KAKASI版)」と同じテキストを使って実行してみよう。

まず、「元のテキスト」として、以下のWikipediaの引用文を入れる。これは「PHP: Hypertext Preprocessor」からの抜粋である。
PHP: Hypertext Preprocessor(ピー・エイチ・ピー ハイパーテキスト プリプロセッサー)とは、動的にHTMLデータを生成することによって、動的なウェブページを実現することを主な目的としたプログラミング言語、およびその言語処理系である。
PHPは、HTML埋め込み型のサーバサイド・スクリプト言語として分類される。この言語処理系自体は、C言語で記述されている。
「比較するテキスト」には、以下の文章を入れてみよう。
PHP(Hypertext Preprocessor;ピー・エイチ・ピー)とは、動的にHTMLデータを生成することによって、動的なウェブページを実現すること目的としたプログラミング言語である。
PHPは、HTML埋め込み型のサーバサイド・スクリプト言語の一種で、処理系自体はC言語で記述されている。
結果は 0.97 である。
2つめの文章は、一見すると元の文章とは異なっているが、じつはWikipediaの引用文の順番を変えただけである。
このような違いでは、かなり高い類似度の値となる。

次に、「比較するテキスト」に以下の文章を入れて実行してみていただきたい。これは「PHPとは何か」(ぱふぅ家のホームページ)の冒頭部分である。
「PHP(Hypertext Preprocessor)」は、オープンソースのサーバ・サイド・スクリプト言語である。
サーバ・サイド・スクリプトとは、データベースサーバなどのサーバ群と Web ブラウザ(クライアント)を結ぶインターフェースの役割をするもので、Webサーバ上で動作する。HTMLに比べて、動的なページを実現することができる。
結果は 0.78 となる。
PHPで2つの文章の類似度を計算する(KAKASI版)」での、最初の比較例では 75.5%、2番目の比較例では 45.1% だった。

ちなみに、PHPとはまったく関係ない以下のテキストを「比較するテキスト」に入れてみると――
さきたま古墳公園(埼玉県行田市大字埼玉4834)は、8基の前方後円墳と1基の円墳が集中する東日本最大の古墳遺跡である。
1938年(昭和13年)8月に国の史跡の指定を受け、1968年(昭和43年)には金錯銘鉄剣(きんさくめいてっけん)が出土したことで一躍脚光を浴びた。
類似度は 0.52 になる。0.6以下ということで、類似度は低いと言えよう。
一方、KAKASI を使った結果では 9.0% だった。

参考サイト

(この項おわり)
header