PHPで日本文の“要約もどき”を行う

(1/1)
日本文の要約を自動的に行うことは、なかなか難しい。
今回は、Yahoo!JAPANの「日本語係り受け解析」を利用し、ベースとなる述語と、それを修飾する文節を取り出すことで、“要約もどき”を行ってみることにする。

(2022年1月29日)日本語係り受け解析V2対応,PHP8対応,リファラ・チェック改良

目次

サンプル・プログラムの実行例

PHPで日本文の要約もどきを行う

サンプル・プログラム

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

日本語係り受け解析

日本語係り受け解析」は、入力パラメータとしてJSON文字列をPOSTで、User-Agentに Yahoo! JAPAN Webサービス アプリケーションID を指定し、出力結果がJSONで戻るというWebAPIである。
WebAPIのURL
URL
https://jlp.yahooapis.jp/DAService/V2/parse

入力パラメータ
フィールド名 要否 内  容
id 必須 JSON-RPC 2.0のid。値は任意で、指定した値がレスポンスのidに返る。
jsonrpc 必須 "2.0" 固定。
method 必須 "jlp.daservice.parse" 固定。
params q 必須 解析対象のテキスト。解析可能な単位は1文のみ。
応答データ構造(json) id id jsonrpc 2.0 result chunks head 修飾する文節の番号。修飾先がなければ -1 id 文節の番号 tokens _0 形態素の表記 _1 形態素の読みがな _2 形態素の基本形表記 _3 形態素の品詞 _4 形態素の品詞細分類 _5 形態素の活用型 _6 形態素の活用形 chunks head 修飾する文節の番号。修飾先がなければ -1 id 文節の番号 tokens _0 形態素の表記 _1 形態素の読みがな _2 形態素の基本形表記 _3 形態素の品詞 _4 形態素の品詞細分類 _5 形態素の活用型 _6 形態素の活用形

準備:アプリケーションIDなど

0014: // 初期化処理 ================================================================
0015: define('INTERNAL_ENCODING', 'UTF-8');
0016: mb_internal_encoding(INTERNAL_ENCODING);
0017: mb_regex_encoding(INTERNAL_ENCODING);
0018: define('MYSELF', basename($_SERVER['SCRIPT_NAME']));
0019: define('REFERENCE', 'https://www.pahoo.org/e-soul/webtech/php06/php06-47-01.shtm');
0020: define('TITLE', '日本文の要約もどき');
0021: define('REQUEST_KAKARIUKE_URL', 'https://jlp.yahooapis.jp/DAService/V2/parse');
0022: 
0023: //リファラチェック+リリースフラグの設定
0024: if (isset($_SERVER['HTTP_HOST']) && ($_SERVER['HTTP_HOST'] == 'localhost')) {
0025:     define('FLAG_RELEASE', FALSE);
0026:     define('REFER_ON', '');
0027:     ini_set('display_errors', 1);
0028:     ini_set('error_reporting', E_ALL);
0029: else {
0030:     //リリース・フラグ(公開時にはTRUEにすること)
0031:     define('FLAG_RELEASE', TRUE);
0032:     //リファラ・チェック(直リン防止用;空文字ならチェックしない)
0033:     define('REFER_ON', 'www.pahoo.org');
0034: }
0035: 
0036: //表示幅(ピクセル)
0037: define('WIDTH', 600);
0038: 
0039: //Yahoo! JAPAN Webサービス アプリケーションID
0040: //取得方法https://www.pahoo.org/e-soul/webtech/php06/php06-01-02.shtm#Yahoo
0041: define('APPLICATION_ID', '**************************************');
0042: 
0043: //入力テキスト(初期値)
0044: define('SAMPLE_TEXT', '犬吠埼灯台は、1874年に英国人リチャード・ヘンリー・ブラントンの設計により建築された、れんが造りの灯台で、日本で24番目に点灯された。高さは31.57メートルあり、99段のらせん階段を昇った眺望は、太平洋の孤島に身をおいた錯覚を覚えるほど雄大である。');

Yahoo!JAPANのWebAPI「日本語形態素解析」を利用するため、Yahoo! JAPAN Webサービス アプリケーションID を取得する必要がある。その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPIの登録方法」を参照されたい。
取得したIDは定数 APPLICATION_ID に格納する。
その他、変更不可と記載のない定数は任意に変更して構わない。

解説:テキストの分解

0250: /**
0251:  * 複数文要約インターフェース
0252:  * @param   string $sentence 要約するテキスト
0253:  * @return  string 要約もどき
0254: */
0255: function pseudodigest($sentence) {
0256:     $arr = mb_split("[。.]", $sentence);
0257:     $pseudodigest = '';
0258:     foreach ($arr as $str) {
0259:         if ($str == '')    continue;
0260:         if (($res = pseudodigest_sub($str . '')) == FALSEreturn FALSE;
0261:         $pseudodigest .= $res;
0262:     }
0263: 
0264:     return $pseudodigest;
0265: }

日本語係り受け解析は、一度の呼び出しで1文しか解析できないため、入力されたテキストを句点で分解する。

解説:要約もどき

0186: /**
0187:  * 「Yahoo!JAPAN日本語係り受け解析」を用いて日本文を要約する
0188:  * @param   string $sentence 要約するテキスト(1文)
0189:  * @return  string 要約もどき/FALSE:WebAPIエラー
0190: */
0191: function pseudodigest_sub($sentence) {
0192: //WebAPIにパラメータをPOST渡しする
0193:     $url = REQUEST_KAKARIUKE_URL;
0194:     $post = array(
0195:         'id'       => '1234-1',                   //ダミー
0196:         'jsonrpc'  => '2.0',                  //固定値
0197:         'method'   => 'jlp.daservice.parse',  //固定値
0198:         'params'   => array(
0199:             'q' => (string)$sentence           //対象テキスト
0200:         )
0201:     );
0202:     $json = json_encode($post);
0203: 
0204:     //WebAPIにパラメータをPOST渡しする
0205:     $stream = stream_context_create(array('http' => array(
0206:         'header'  => "Content-Type: application/json\r\n" .
0207:                     "User-Agent: Yahoo AppID: " . APPLICATION_ID . "\r\n",
0208:         'method'  => 'POST',
0209:         'content' => $json,
0210:     )));
0211: 
0212:     //WebAPIリクエスト
0213:     $res = @file_get_contents($urlFALSE$stream);
0214:     if ($res == FALSE)  return FALSE;
0215: 
0216:     //応答を配列へ代入
0217:     $results = json_decode($res);
0218:     if (! isset($results->result->chunks)) return FALSE;
0219:     $cnt = 0;
0220:     foreach ($results->result->chunks as $chunk) {
0221:         $head = isset($chunk->head) ? (int)$chunk->head : (-1);
0222:         $id   = isset($chunk->id)   ? (int)$chunk->id   : (-1);
0223:         $phrase = '';
0224:         foreach ($chunk->tokens as $token) {
0225:             $phrase .= (string)$token[0];
0226:         }
0227:         $items[$id]['head']   = $head;
0228:         $items[$id]['phrase'] = $phrase;
0229:     }
0230: 
0231:     //要約
0232:     $base = '';
0233:     foreach ($items as $id=>$item) {
0234:         if ($item['head'] < 0) {
0235:             $base = $item['phrase'];
0236:             break;
0237:         }
0238:     }
0239:     $pseudodigest = '';
0240:     foreach ($items as $item) {
0241:         if ($item['head'] == $id) {
0242:             $pseudodigest = $pseudodigest . $item['phrase'];
0243:         }
0244:     }
0245:     $pseudodigest .= $base;
0246: 
0247:     return $pseudodigest;
0248: }

要約を行うのはユーザー関数 pseudodigest_sub である。
前半で日本語係り受け解析を呼び出し、文節番号をキーに、修飾番号と表記を配列 $items に格納する。

後半が要約もどきの処理である。
修飾番号が無い(-1 が格納されている)文節がベースとなる述語である。これを探しだし、それを修飾している文節を並べる。

参考サイト

(この項おわり)
header