【WordPressカスタマイズ相談】現役プログラマが解決策を教えます

WordPress(ワードプレス)のお悩み、うまくいかなくてお困りなこと、不具合調査、新規制作依頼まで、ウェブアプリケーションエンジニアがあなたをサポートします。

スクレイピングするPHPプログラムの作り方【Simple html dom prser】

f:id:jsaz:20170114165413j:plain
ウェブサイトから必要な情報を収集できるスクレイピングですが、最近はjavascriptPythonでもとても簡単にできるようになってきました。


PHP」というプログラミング言語はお仕事にしているプロ級の方から、ブロガーやアフィリエイターの方々まで幅広く学習・実践できるプログラムです。

そんな初心者でも比較的簡単に使うことができるPHPで「Simple HTML DOM Parser」を使ったウェブスクレイピングプログラムの作り方・使い方をご紹介します。

Webスクレイピングとは

あるウェブサイトに自分の欲しい情報があるとします。

そのサイトにはRSSAPIなどが用意されておらず、その情報を得るためには毎日もしくは1ページずつアクセスする必要があります。


これはとても面倒な作業になりますよね。
そのような作業を機械(プログラム)が行うことをWebスクレイピングといいます。
クローラー」や「クローリング」と読んだりもします。

取得した情報は自分の欲しい形で加工・整形して資料にまとめたり、自分のサイトで活用したりできます。

PHP Simple HTML DOM Parser


簡単に説明します。

PHPのライブラリでrequireするだけで使える
HTMLの文字、要素 (element)、属性 (attribute)を指定すると取得できる
取得したいページのHTML解析スキルが必要となる

ウェブサイトの構成が複雑であれば、少し頭を使う必要があります。
個人の方がこだわって作られたサイトや、ひと昔前のサイト等はHTMLが複雑なこともあるので難しいかもしれません。

HTMLの要素と属性 | HTML解説

simple_html_domの使い方


良くわかる使い方のページはコチラです。
PHP Simple HTML DOM Parserの使用方法 - Webスクレイピング ライブラリ

まずは、ライブラリをrequireします。

<?php
require_once('simple_html_dom.php');

CakePHP等のフレームワークで利用の場合は

<?php
//Vendor/simple_html_dom.phpを読み込む(CakePHP2の場合)
App::import('Vendor', 'simple_html_dom');

simple_html_domが使えるようになるので、対象(読み込みたい)ページのURLを指定してHTMLを読み込みます。
なお、下記file_get_htmlはURLを指定してウェブページ(自サーバー内のHTMLファイルもOK)を読み込みますが、他にstr_get_html(文字列から)を使うことも可能です。

<?php
//対象ページのURL
$url = "http://soudan.hatenablog.jp";
//文字化け対策
mb_language("Japanese");
//ウェブページのデータを読み込み
$html = file_get_html($url);

$dataがnullでなければ、HTMLデータを取得できています。
あとはfindを使い、欲しいデータだけを取り出していきます。


スクレイピングプログラムの作り方

記事一覧ページから詳細ページのURLを抜き出す方法

記事一覧の各記事のクラスがpostの場合、その領域内のリンク(各記事詳細ページURL)を取得する
【ネストのパターン】

<?php
$list = array();
foreach( $html->find( 'div.post' ) as $element ) {
	$list[] = array(
		'title' => $element->find( 'a',0 )->plaintext,
		'url' => $element->find( 'a',0 )->href,
	);
}
var_dump($list);

こうするとページ名とURLの一覧($list)を取得することが可能です。

ちなみに、次ページへ送りたいときはあらかじめページ指定のURLを解析する必要があります。

http;//---.com/page/2
http;//---.com/page/3
http;//---.com/page/4

http;//---.com/?page=2
http;//---.com/?page=3
http;//---.com/?page=4

といったパターンが多いです。

とりあえず20ページ分スクレイピングできるサンプルプログラムはこんな感じです。

<?php
//ページングURL
$base_url = "http://soudan.hatenablog.jp/pgae/%s";
for ($page=1; $page<=20; $page++) {
	//URLにページをセットする
	$url = sprintf($base_url, $page);
	…ウェブページを読み込み解析する…

whileを使ってページャーエリアにリンクがあるかどうかをfindで調べるのがベストな方法かもしれません。
個別で解析をご希望の方はご相談ください


●記事詳細ページからデータを抜き出す方法

・固有のURLを取得:ヘッダーのmeta relのshortlink

<?php
$shortlink_elem = $html->find('head link[rel=shortlink]',0);
$shortlink = $shortlink_elem->href


・記事タイトルを取得:div#mainの中のdiv.entry-contentの中の最初のh1

<?php
$title_elem = $html->find('div#main div.entry-content h1', 0);
$title = $title_elem->plaintext;


・複数あるタグを取得:div.tag領域のリンクのテキストを1つずつ取得し配列にセット

<?php
foreach( $html->find('div#main div.tag a') as $tag ) {
	$tags[] = $tag->plaintext;
}

スクレイピングデータの加工の方法


取得したデータは必要な箇所だけ抜き出してデータベースへ保存したり、テキストファイルにまとめたりすることが多いと思います。
よくあるパターンとその時使いそうなPHP関数を上げておきます。
※下記サンプルは取得した文字列データに対して行う作業です。

正規表現で記事から画像パスだけ抜き出す

<?php
preg_match_all('/<img(?:.*?)src=[\"\'](.*?)[\"\'](?:.*?)>/e', $description, $img_path_list);


・URLの?以降を削除する
(対象の文字より後ろの文字を削除するときに使う)

<?php
$url2= mb_substr($url,0,strpos($url, '?'));


様々なデータ取得と解析、加工のサンプルをあげていきました。
サイトによって作りは異なるため、一筋縄ではいかないこともあります。


「どうしてもスクレイピングが上手くいかない」、「自分では作れないので0から作って欲しい」等のリクエストはココナラからお問い合わせください。
WordPressと連携し記事に投稿することも可能です。

おまけ

UAを変更してスクレイピングする方法はma_meさんが書かれています。
スマホ専用ページへのアクセスならこの方法が良いと思います。
qiita.com


文字化けがどうしても解決しない場合はエンコードしてみる
qiita.com


Goutteという別のライブラリも使える、Simple html dom prserとのパフォーマンスを比較
qiita.com