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


ワードプレス魔改造 オートブログ講座2 第二十六回目 スクレイピングで取得したデータをクリーニングする

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

前回はスクレイピング(抽出)をしたのですが、取得したデータには余計な改行やタブ、スペースといった見えない文字列が付随しています。そこでデータを使えるようにクリーニングをする必要があります。
例えば以下のようなウェブページがあるとします。

▼なぜ仕事の早い人は酒や煙草にはまるのか

せっかち度、すなわち時間割引率が高い人ほど、近視眼的な行動に走りやすい。

これを前回作ったサンプルコードで実行してみます。

▼外部サイトにアクセスして必要な情報をスクレイピングする

前回はスクレイピング(抽出)をしたのですが、取得したデータには余計な改行やタブ、スペースといった見えない文字列が付随しています。そこでデータを使えるようにクリーニングをする必要があ
/25-Ylq/01.php

するとウェブページ内の「<p>タグ」は以下のようになっています。
データは配列で取得するので[0]とか[1]というのは配列の番号で、説明のために便宜的につけてあります。

[0] => PRESIDENT Online TOP>人材・キャリア>キャリア
[1] => 2009年9月12日(土)
[2] =>  		PRESIDENT 					2009年10月5日号 
[3] => 
[4] => 1965年生まれ。京都大学経済学部卒、同大学院経済学研究科修了。同大学院経済学研究科助教授などを経て、2007年から現職。著書に『行動健康経済学』(共著)など。
[5] => 今日100円を受け取るか、1年後に同じ100円を受け取るかと言われれば、誰でも今日受け取ったほうがいいと言うだろう。しかし、現在の100円と1年後の110円とどちらがいいかと言われたらどうするか。さらに、1年後の金額を130円にしたらどうだろう……。
[6] => こんなふうに受け取れる金額を少しずつ増やし、いくらまで上げれば1年待てるかを調査する。例えば、今日の100円と1年後の150円が満足できる等価だったとしよう。この比率が「時間割引率」になる。
[7] => 時間割引率とは、将来を「割り引く」割合のことだ。現在の利得と将来の利得の交換比率を表すが、その比率は利子率で測るので先の例でいえば今日の100円と1年後の150円が等価だったとすれば、割引率は50%となる。
[8] => 冷静に考えれば、100円より150円のほうが、価値が高い。それならば今日我慢して、1年後に150円を受け取ったほうがいいと思うはずだ。しかし、人間は誰しも、将来の利益より、目先の利益を優先する傾向を持っている。時間割引率はそんな人間の「せっかち度」を測るモノサシでもある。
[9] => 人間なら、誰しもある程度はせっかちな性癖を持っているものだ。そもそも人類に農耕という、長期的な利益を待つシステムが確立される以前の社会では、将来のことなどより、目の前のチャンスを逃さない人のほうが生き残る確率が高かった。人間がせっかちなのはこの頃の名残であると考えられる。人間だけではなく、ハトやネズミのような動物も同じような性向を持つ。
[10] => ただし、せっかちの度合いには明らかに個人差がある。せっかち度、すなわち時間割引率が高い人ほど、近視眼的な行動に走りやすい。
[11] => 
[12] => [孫正義の仕事術]
[13] => 孫正義氏の何が周囲を心酔させるのか。その答えの鍵は「人たらし」にある!  		 			できない理由とできる理由、数が多いのはどっちだ? 			成功する脳習慣とは何か【1】 -対談:孫 正義×茂木健一郎 			孫 正義の大ボラ:聴衆を虜にする「アファメーション効果」 		 	
[14] => [ソーシャルネットワーク活用]
[15] => ビジネスに、生活に、どう使い分ければ効率的に情報を得ることができるのだろう。  		 			STAP疑惑暴いたSNS“オープン”な破壊力 			ローソンの「あきこちゃん」フォロワー1500万人の秘密 			マーケティング機能強化で、Twitterはあらゆるメディアの橋渡しツールになる 		 	
[16] => 夏の魚「ハモ」を味わう
[17] => 孫正義の褒め方・叱り方
[18] => ときめきの肉 ビヨンド
[19] => 東大合格は簡単だ!
[20] => Copyright © PRESIDENT Inc. All rights reserved.

データを見ると3番目と11番目のデータに空行があります。空行は不要ですよね。
それから文字数が短い行がありますね。これは文章ではなく恐らくはメニューとかリンクテキストなので不要です。
あともしかすると文字列の中には不適切な単語も存在するかもしれません。そういう行は削除する必要があります。また必要な文字列もあります。文章だと判断する最も簡単なものは句点の「。」があるかないです。句点のある行だけを抽出すればほぼ文章だけを抽出できます。

以上を解決する自作関数を用意します。
関数の書式は以下のような感じになります。

クリーニング済み配列 = ARRAY_CLEAN( 配列 , 最低文字数 , NGワード , 必要な文字列 , テストオプション );

用意する引数ですが「最低文字数」は数値で指定し、「NGワード」と「必要な文字列は配列で用意します。
テストオプションはテスト用に文字数を表示するためのオプションで省略できます。「1」を指定するとオプションが有効になります。

//最低文字数
$MIN_STRING_LEN = 100;

//ソース内NGワードリスト
$A_NG_WORD = array();
$i = 0;
$A_NG_WORD[$i] = 'javascript';
$A_NG_WORD[++$i] = '当ページ';
$A_NG_WORD[++$i] = '当サイト';
$A_NG_WORD[++$i] = '当方';
$A_NG_WORD[++$i] = '弊社';
$A_NG_WORD[++$i] = 'All Rights Reserved';
$A_NG_WORD[++$i] = '著作権';
$A_NG_WORD[++$i] = '無断転載';
$A_NG_WORD[++$i] = '転用';
$A_NG_WORD[++$i] = '商標';
$A_NG_WORD[++$i] = '死す';
$A_NG_WORD[++$i] = '死ね';
$A_NG_WORD[++$i] = '殺す';
$A_NG_WORD[++$i] = '殺せ';

//必須ワードリスト
$A_NEED_WORD = array();
$i=0;
$A_NEED_WORD[++$i] = '。';


//配列から空要素を削除し最低文字数以下を削除しインデックスを振り直す(前後の空白も削除)
function ARRAY_CLEAN( $array , $length , $ng_word , $need_word , $option = 0 )
{

	//配列の中の空要素を削除する
	$array = array_filter( $array , "strlen" );

	//配列の添字を振り直す
	$array = array_values( $array );

	$i = 0;

	//配列をループで処理する
	foreach( $array as $element )
	{

		//NGワードをループで処理する
		foreach( $ng_word as $word )
		{

			//パターンに変数を使う(大文字小文字区別なし)
			$pattern = '/' . $word . '/iu';

			//NGワードが含まれていたら
			if( preg_match( $pattern , $array[$i] ) )
			{
				//配列から削除
				unset( $array[$i] );
				//ループを抜ける
				break;
			}
		}


		//必須ワードをループで処理する
		foreach( $need_word as $n_word )
		{
			//パターンに変数を使う(大文字小文字区別なし)
			$pattern = '/' . $n_word . '/iu';

			//必須ワードが含まれていなければ
			if(! preg_match( $pattern , $array[$i] ) )
			{
				//配列から削除
				unset( $array[$i] );
				//ループを抜ける
				break;
			}
		}


		//前後の空白文字を削除
		$array[$i] = trim( $array[$i] );

		//先頭の全角スペースを削除
		$array[$i] = preg_replace('/^[ ]+/u', '', $array[$i] );


		//オプションがあれば文字数を表示
		if( $option === 1 )
		{
			$array[$i] = '(' . mb_strlen( $array[$i] , "UTF-8" ) . ') : ' . $array[$i];
		}

		//最低文字数以下であれば(全角も1文字でカウント)
		if( $length >= mb_strlen( $array[$i] , "UTF-8" ) )
		{
			//配列から削除
			unset( $array[$i] );
		}

		$i++;
	}

	//配列の添字を振り直す
	$array = array_values( $array );

	return $array;

}

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

関連記事