ITごはん

ITを活用したい人、ITで何か作りたい人、そんなITでごはんを食べる人のためのブログ

【PHP】Simple HTML DOM Parserでお気軽にスクレイピング

はじめに

PHPではすっかり定番となった感がありますが、「Simple HTML DOM Parser」で スクレイピングを行ってみます。 「Simple HTML DOM Parser」は、HTMLを解析してDOM形式で取得できて、jQueryみたいな感覚で、気軽にデータを抽出出来ます。

今回は、URLのリストのファイルから、スクレイピングして、その結果をCSVファイルに出力するという一連の処理を行ってみます。 なお、くれぐれも悪用禁止です。

※DOM形式(Document Object Model)について知らない人は、以下でイメージをささっと掴みましょう。 http://piyo-js.com/05/dom.html

使い方

大まかな処理のイメージは以下の様な感じです。

f:id:HIDEKIT:20140613175649p:plain

スクレイピングしたいURLが記載されているファイル(read_url.txt)を用意します。

//read_url.txt
http://www.yahoo.co.jp/
http://www.livedoor.com/
//ダブルスラッシュでコメントも付けれます
http://www.hatena.ne.jp/

こちらが一行ずつスクレイピングされます。

コードは以下です。

//index.php
<?php

include "simple_html_dom.php";

echo "処理開始\n";

//結果配列(2次元配列)
$data =array();

//読み込みファイルの行カウンター
$count = 0;

//ファイルの読み込み
$fp = fopen('read_url.txt', 'r');

//SJISにエンコード
$header = array(mb_convert_encoding('企業名', "SJIS-win", "UTF-8"), mb_convert_encoding('公式サイト', "SJIS-win", "UTF-8"));
    array_push($data, $header);

if ($fp) {
    
    //ファイルをロック
    if (flock($fp, LOCK_SH)) {
        
        //EOFまで繰り返す
        while (!feof($fp)) {
            
            //カウンターをインクリメント
            $count++;
            echo $count. "行目を処理\n";
            
            $line_url = fgets($fp);
            
            //先頭行が//の場合、コメントのため読み飛ばし
            if (substr($line_url, 0,2) == "//") {
                continue;
            }
            
            
            
            //スクレイピング
            scrapingHtml($line_url, $data);
            
        }

        flock($fp, LOCK_UN);
    } else {
        echo "ファイルロックに失敗しました";
    }
}

fclose($fp);

//結果ファイルに出力
$file = fopen("result.csv", "w");
foreach ($data as $line) {
    fputcsv($file, $line);
}
fclose($file);

echo '正常終了';


//HTMLをスクレイピング
//注意:$dataは参照渡し
function scrapingHtml($read_url, &$data) {

    //出力内容を保持する二次元配列
    //$result_data = array();
    
    //$html = file_get_html('http://www.jpubb.com/listnl/list.php?listed=2&ind=%E6%83%85%E5%A0%B1%E3%83%BB%E9%80%9A%E4%BF%A1');
    $html = file_get_html($read_url);
    foreach ($html->find('table[class=corpTable] tr') as $element) {

        //会社名を取得
        $name = $element->find('td[class=name]', 0)->plaintext;

        //会社名がブランクの場合、読み飛ばし
        if (empty($name)) {
            continue;
        }

        //公式サイトを取得
        $url = $element->find('td[class=other] a', 2)->href;


        $company = array(mb_convert_encoding($name, "SJIS-win", "UTF-8"), mb_convert_encoding($url, "SJIS-win", "UTF-8"));

        array_push($data, $company);
    }
    
    //return $result_data;
}

CSVで出力したいので、抽出結果を2次元配列で保持します。

    $html = file_get_html($read_url);

で、DOMのオブジェクトを返すので、そちらをもとに、

$html->find('table[class=corpTable] tr')

でtable要素のclass名cropTableのtrを取得するという、指示になっています。 この部分は、取得したいサイトによって色々変えてみてください。

リンク

http://www.crystal-creation.com/web-app/tech/programming/php/library/simplehtmldom/