この記事はブロックされています。続きを読みたい方はログインをして下さい。会員ではない方は新規会員登録をして下さい。


ワードプレス魔改造 オートブログ講座2 第二十七回目 よりキーワードに関連性のある文章のみを抽出する

  • ワードプレスで作るオートブログ講座2

前回はスクレイピングしたデータをクリーニングする方法を紹介しました。
今回はオートブログの要である「よりキーワードに関連性のある文章のみを抽出する」方法です。
ウェブページには複数の情報が存在します。ひとつのウェブページに異なる内容の記事が複数存在する場合もあります。すると困ったことが起きます。どの文章が必要なのか判断が付かないことです。

これを解決するために(完全には解決できないが)初期の検索エンジンが採用していた方法を参考にします。
まずウェブページ内の単語を調べあげて、頻出単語を探し出します。
例えば頻出単語として「ビジネス」と「拡大」という単語が上位にあれば、その単語はおそらくはそのウェブページを理解するキーワードとなると予想できます。

キーワードが分かれば、次にそのキーワードが出現する文章を特定します。
そのキーワードが出現する文章は、そのキーワードを説明するだろうと予測できます。そして、その前後の文章は関連性の高い文章だと考えられます。逆に言えば、キーワードが現れない文章の周辺は関連性が低いと考えられます。
昔の検索エンジンは単純にキーワードがどのくらいウェブページに現れるかを参考にしていました。

ではやってみましょう。
まずウェブページの中でHTMLタグの構造に着目し、キーワードが含まれるタグを抽出します。
そのタグは「<p>、<meta>、<h1>、<h2>、<strong>、<b>」と言ったタグです。他にもありますが、これらがメジャーでしょう。これらのタグの抽出は以前やりましたね。

配列として取得してあるので、まずひとつの(二次元)配列にまとめます。
それを自作関数の「JOINT_CONTENT関数」で一つの文字列に連結します。

//連結する配列を用意
$A_joint_content = array( $A_P , $A_META , $A_H1 , $A_H2 , $A_STRONG , $A_B );

//引数の配列を全てひとつの文字列に連結する
$content = JOINT_CONTENT( $A_joint_content , "" );

//2次元配列をひとつの文字列にする//////////////////////////////////////////////
function JOINT_CONTENT( $A_joint_content , $border )
{

	//配列の数だけ処理する
	foreach( $A_joint_content as $array )
	{
		//連結
		$content .= implode( $border , $array );
	}

	//連結された文字列を返す
	return $content;

}

これを自作関数「CONTENTS_2_KEYWORD」に渡し、単語境界で分かち書きをして頻出単語をピック・アップします。これについては以前やったので説明を省略します。使用する単語境界は「漢字とカタカナ」の組合せにします。この方が上手くいくようです。

//抽出する文字種別
$GET_CHAR_PAT = 2;
//0…フル
//1…漢字とひらがなとカタカナ
//2…漢字とカタカナ
//3…漢字
//4…ひらがなとカタカナ
//5…ひらがな
//6…カタカナ
//7…英数字

//漢字境界で分かち書きをして結果を配列で取得
list( $content , $A_rank ) = CONTENTS_2_KEYWORD( $content , $GET_CHAR_PAT , null );

配列「$A_rank」には頻出単語が出現順に格納されています。
次に自作関数「PICKUP_FREQUENT_WORD」で上位のキーワードが存在する文章(主文)だけを抽出します。


//頻出ワードをピックアップする
主文配列 = PICKUP_FREQUENT_WORD( クリーニング済み文章配列 , メタタグ配列 , キーワード頻出配列 , 比較キーワード順位 , 取得する文章の行数 );

用意する引数ですが「比較キーワード順位」は「$A_rank」の上位何位までのキーワードを比較するか整数で指定します。「取得する文章の行数」はキーワードが見つかった文章より、改行を1ブロックとしてなんブロックまで取得するか整数で指定します。「2」を指定すると、キーワードが見つかった文章とその次の文章を1つ含みます。

//比較するキーワード順位
$LIMIT_RANK = 7;

//取得するテキストブロックの数
$GET_TEXT_BLOCK_NUM = 2;

//頻出ワードをピックアップする
$A_all_main_text = PICKUP_FREQUENT_WORD( $A_text_block , $A_META , $A_rank , $LIMIT_RANK , $GET_TEXT_BLOCK_NUM );

//頻出単語が含まれる文をピックアップし多次元配列を返す/////////////////////////
function PICKUP_FREQUENT_WORD( $A_text_block , $A_META , $A_rank , $limit, $get_text_block_num )
{

	//主文配列を用意
	$A_all_main_text = array();

	if( count( $A_text_block ) === 0 )
	{
		return $A_all_main_text;
	}



	$i = 0;
	//本文の中から頻出単語が含まれる文をピックアップする
	foreach( $A_rank as $key => $value )
	{

		$ii = 0;
		//テキストブロックを処理
		foreach( $A_text_block as $text )
		{

			//頻出数を配列にセット
			$A_frequent[ $ii ] = mb_substr_count( $text , $key , 'UTF-8' );

			//メタ情報にタグと頻出数をセット
			$A_META[ 'tag' ][ $key ] += $A_frequent[ $ii ];

			$ii++;
		}

		$i++;

		//規定数処理したら抜ける
		if( $i >= $limit )
		{

			//テキストブロックを規定数取得する
			for( $t = 0; $t < $get_text_block_num; $t++ )
			{
				//第一文の行の位置を取得
				$first_row = array_search( max( $A_frequent ) , $A_frequent );

				//第一文と第二文を配列にセット
				$A_main_text[$t] = $A_text_block[ $first_row ];

				//一位を削除
				unset( $A_frequent[ $first_row ] );

			}

			//全主文配列に主文配列を追加
			$A_all_main_text = $A_main_text;
			break;

		}
	}

	//メタ情報を追加
	$A_all_main_text[ 'meta' ] = $A_META;

	//全主文配列を返す
	return $A_all_main_text;

}

以下がサンプルコードです。コメントがたくさんあるので分かりやすいと思います。

関連記事