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


ワードプレス魔改造 オートブログ講座2 第二十五回目 外部サイトにアクセスして必要な情報をスクレイピングする

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

前回は分かち書きでコンテンツからキーワードを作成しましたが、今回は外部サイトにアクセスしてHTMLソースから必要な情報をスクレイピング(抽出)します。外部サイトへのアクセスには「cUrl」を使います。

外部サイトにアクセスしてスクレイピングできるとなにがどうなるかというと、例えばYahoo!のトップページにアクセスして、トップページに表示されているニュースの一覧を取得できたりします。また株価情報にアクセスして株価を取得できたりします。
オリジナルのブラウザやボットプログラムが作れてしまいます。
今まで人力でやっていたものをプログラムに任せられるわけです。

サイトの更新情報についてはRSSフィードがあればそれで十分なのですが、RSSフィードで提供されていないデータについては直接PHPでアクセスしてぶっこ抜きます。

まず「cUrl」の設定を決めます。色んなオプションがあるのですが、使うものは限られています。
ポイントは「タイムアウト時間」「最大取得文字数」「偽装ユーザーエージェント」の3つです。
「タイムアウト時間」はアクセスするサーバーの反応が無い時に何秒待つかです。混雑したサーバーであれば遅いので待つ秒数を長くする必要があります。しかし、あまり長くなりすぎると自分のサーバーがタイムアウトしてしまうので10~20秒程度にしておきます。

「最大取得文字数」はアクセスするHTMLを何文字取得するかです。異常に長いHTMLだとメモリエラーになる可能性があるので制限を設けておきます。

「偽装ユーザーエージェント」は相手のサーバーがアクセス解析をしている時に表示されます。
ユーザーエージェントは要するに使用しているブラウザのことです。
たまにロボット避けにユーザーエージェントが正しくないとコンテンツを表示しないトラップをかけているサイトもあるので、なにか適当にPCで見たときのユーザーエージェントを入れておきます。

▼自分のユーザーエージェントの確認

ユーザーエージェント確認はあなたが今使用しているブラウザのユーザーエージェントを確認・表示します。

▼ユーザーエージェント一覧

アクセスするURLはサンプルではフォームから取得しています。直接指定しても構いません。

//フォームからURLを取得する
$URL = $_POST[ 'url' ];

//タイムアウト時間(秒)
$TIMEOUT = 20;

//HTMLを読み込む最大文字数(エラーが出るなら小さくする)
$MAX_LEN = 20000;

//偽装ユーザーエージェント
$UA = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.52 Safari/537.36';

この情報を配列に入れて「cURL」に渡すとアクセスしてくれます。

//cURLに値をセットする
$cURL_params = array
(
	'timeout'	=> $TIMEOUT,	//タイムアウト時間
	'buffer'	=> $MAX_LEN,	//最大バッファサイズ
	'user_agent'=> $UA,			//ユーザーエージェント
	'url'		=> $URL,		//アクセスするURL
);

オートブログでは「CURL_GET_CONTENTS()」という関数を用意しています。

//外部サイトコンテンツを取得する///////////////////////////////////////////////
function CURL_GET_CONTENTS( $params )
{

	//オブジェクトを作成
	$ch = curl_init();

	//ヘッダ文字列を一緒に出力するかどうかのBoolean値。邪魔なのでfalseに
	curl_setopt( $ch , CURLOPT_HEADER , false );
	//curl_execの返り値を文字列にする為のBoolean値。これをtrueにしないとデータが直接出力される
	curl_setopt( $ch , CURLOPT_RETURNTRANSFER , true );


	//URLがセットされていれば
	if( isset( $params[ 'url' ] ) )
	{
		//アクセスURLをセット
		curl_setopt( $ch , CURLOPT_URL , $params[ 'url' ] );
	}
	else
	{
		return 0;
	}


	//タイムアウト時間がセットされていれば
	if( isset( $params[ 'timeout' ] ) )
	{
		//タイムアウト時間をセット
		curl_setopt( $ch , CURLOPT_TIMEOUT , $params[ 'timeout' ] );
	}


	//送信メソッドがセットされていれば
	if( isset( $params[ 'method' ] ) )
	{
		//GETであれば
		if( $params[ 'method' ] == "get" )
		{
			//GET形式にセット
			curl_setopt( $ch , CURLOPT_HTTPGET , true );
		}
		//POSTであれば
		else if( $params[ 'method' ] == "post" )
		{
			//POST形式にセット
			curl_setopt( $ch , CURLOPT_POST , true );
		}
	}


	//送信メソッドがセットされていれば
	if( isset( $params[ 'formValueArray' ] ) )
	{
		//送信する値をセット
		curl_setopt( $ch , CURLOPT_POSTFIELDS , $params[ 'formValueArray' ] );
	}


	//ユーザーエージェントがセットされていれば
	if( isset( $params[ 'user_agent' ] ) )
	{
		//送信する値をセット
		curl_setopt( $ch , CURLOPT_USERAGENT , $params[ 'user_agent' ] );
	}


	//読み込むバッファサイズがセットされていれば
	if( isset( $params[ 'buffer' ] ) )
	{
		//送信する値をセット
		curl_setopt( $ch , CURLOPT_BUFFERSIZE , $params[ 'buffer' ] );
	}


	//設定に基づきアクセス
	$result = curl_exec( $ch );

	//クローズする
	curl_close( $ch );

	//結果を返す
	return $result;

}

こんな感じで使います。

$content = @CURL_GET_CONTENTS( $cURL_params );

「$content」には取得に成功するとHTMLが入っています。ただの文字列です。
関数の頭に「@」を付けておくとPHPの警告が出ても非表示にできます。
URLがアクセス出来ない場合もあるので、警告はオフにしておきます。

次に「$content」を加工したりスクレイピングします。
スクレイピングにはお馴染みの「Simple HTML DOM Parser」ライブラリを使います。
スクレイピングする前にHTMLをちょっとお掃除しておきます。
正規表現で置き換えるのですが、取得したHTMLは文字コードが「Shift-JIS」「EUC」「UTF-8」のいずれかだったりするので、文字コードをUTF-8に変換しておきます。

//文字コードをUTF-8に自動変換
$content = mb_convert_encoding( $contents, 'UTF-8', 'auto');

//styleとscriptタグとコメントタグと を削除しておく
$content = preg_replace( "/<script.*?/script>/is" , "" , $content );
$content = preg_replace( "/<style.*?/style>/is" , "" , $content );
$content = preg_replace( "/<!--.*?-->/is" , "" , $content );
$content = preg_replace( '/ /' , "" , $content );

「Simple HTML DOM Parser」ライブラリはメモリを結構食うので、先に明らかに要らないタグをお掃除しておくとメモリ消費量が抑えられるはず? です。
特にJavaScriptとスタイルシートの記述はかなり長ったらしいのですべて削除します。

「Simple HTML DOM Parser」を使うには「str_get_html()」でオブジェクトを作ります。
これで「Simple HTML DOM Parser」のメソッドが使えるようになります。

//オブジェクトの作成
$html = str_get_html( $content );

たまにHTMLの文字数が多過ぎるととオブジェクトが作成されないので注意が必要です。
その場合は「$MAX_LEN = 20000;」で文字数を調整します。

スクレイピングするタグは「<h1>見出し1」「<h2>見出し2」「<b>太字」「<strong>強調」「<p>段落」「<a>リンク」の6つにしておきます。取得したそれぞれのタグの中身は配列に入れておきます。

//<h1>タグを平文でスクレイピング
$A_H1 		= SCRAPING( $html , 'h1' , 0 );
//<h2>タグを平文でスクレイピング
$A_H2 		= SCRAPING( $html , 'h2' , 0 );
//<b>タグを平文でスクレイピング
$A_B 		= SCRAPING( $html , 'b' , 0 );
//<strong>タグを平文でスクレイピング
$A_STRONG 	= SCRAPING( $html , 'strong' , 0 );
//<p>タグを平文でスクレイピング
$A_P 		= SCRAPING( $html , 'p' , 0 );
//<a>タグを平文でスクレイピング
$A_A 		= SCRAPING( $html , 'a' , 0 );

//スクレイピング処理///////////////////////////////////////////////////////////
function SCRAPING( $html , $tag , $get_Type )
{

	//simple_html_domオブジェクト , 対象タグ , 取得タイプ
	//http://simplehtmldom.sourceforge.net/manual.htm

	$A_scrap = array();

	foreach( $html->find( $tag ) as $element)
	{
		if( $get_Type == 0 )		{ array_push( $A_scrap , $element->plaintext ); }
		else if( $get_Type == 1 )	{ array_push( $A_scrap , $element->innertext ); }
		else if( $get_Type == 2 )	{ array_push( $A_scrap , $element->outertext ); }
		else if( $get_Type == 3 )	{ array_push( $A_scrap , $element->tag );		}
		else				 		{ array_push( $A_scrap , $element->plaintext );	}
	}

	return $A_scrap;

}
あとHTMLの<strong>「&lt;head&gt;タグ」</strong>に含まれるメタ情報は書き方が色々あって、<strong>「Simple HTML DOM Parser」</strong>で一意に取得できないので正規表現で取得しています。取得したデータは「$A_META」配列に入れています。
この時取得しないNGワードを配列で指定しておくと、そのワードが含まれるページは取得しません。
//メタ用の配列を宣言
$A_META = array();

//タイトルを取得
$A_META[ 'title' ] = $html->find( 'title' , 0 )->plaintext;

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

	//タイトルにNGワードが含まれていたら
	if( preg_match( $pattern , $A_META[ 'title' ] ) )
	{
		//処理終了
		return false;
	}
}


//URLをセット
$A_META[ 'url' ] = $cURL_params[ 'url' ];


//ヘッダだけを抽出
$head = $html->find( 'head' , 0 )->innertext;

//<meta>タグのkeywords属性を配列で取得
preg_match( "/<.*?meta.*?keywords(.*?)>/is", $head , $A_meta_keyword );
//content属性だけ抽出
preg_match( "/content.*?=.*?["'](.*?)["']/is", $A_meta_keyword[1] , $A_meta_keyword );

//メタキーワード
$A_META[ 'keyword' ] = $A_meta_keyword[1];


//<meta>タグのdescription属性を配列で取得
preg_match( "/<.*?meta.*?description(.*?)>/is", $head , $A_meta_descri );
//content属性だけ抽出
preg_match( "/content.*?=.*?["'](.*?)["']/is", $A_meta_descri[1] , $A_meta_descri );

//メタディスクリプション
$A_META[ 'description' ] = $A_meta_descri[1];


//<html>タグのlang属性を配列で取得
preg_match( "/<.*?html.*?lang.*?=.*?["'](.*?)["'].*?>/is", $content , $A_lang );

//言語属性
$A_META[ 'lang' ] = $A_lang[1];

これをまとめると以下のようになります。
フォームに取得したいURLを入力して実行ボタンを押すとスクレイピングされた情報が取得できます。

関連記事