PHPでスクレイピング【Goutte vs. Simple HTML DOM Parser】

PHPでスクレイピングをしようと思って検索すると、Simple HTML DOM Parserというライブラリと、Goutteというライブラリが紹介されてあるようです。

昔から存在してPHPスクレイピングの定番になっているのが、Simple HTML DOM Parserらしく、紹介記事も多い。

Goutteは、パフォーマンスが良いらしいが、比較すると記事が少ない。

そこで、本記事は、パフォーマンスバトルと実装方法についてまとめておきます。

「SayMove!のランキングページから、動画のタイトルを取得する」でベンチマーク対決していただきます


 

## 1, Simple HTML DOM Parserのベンチマーク

### 1-1, 導入

[Simple HTML DOM Parserの公式サイト](http://simplehtmldom.sourceforge.net/)にアクセスして、ダウンロードして、作業ディレクトリにsimple_html_dom.phpを配置する。

### 1-2, 実装

```php:
<?php
    require 'simple_html_dom.php';
     
    header('Content-Type: text/html; charset=utf-8');
     
    $kNumberOfSamples = 10; // 何回サンプリングするか
     
    $titles = array();
    $totalOfTime = 0;
    for ($i = 0; $i < $kNumberOfSamples; ++$i)
    {
        // 計測を開始する
        $startTime = microtime(true);
         
        // ランキングにある全てのタイトルを取得する
        $html = file_get_html('http://say-move.org/ranking.php');
        $rank = 0;
        foreach ($html->find('h3.ranking_ttl') as $element)
        {
            $titles[$rank] = $element->text();
            ++$rank;
        }
         
        // 解放する
        $html->clear();
         
        // 計測を終了する
        $totalOfTime += microtime(true) - $startTime;
         
        echo $totalOfTime . '<br/>';
    }
     
    print_r($titles);
    echo '<br/>平均実行時間: ' . $totalOfTime / $kNumberOfSamples;
     
    unset($titles);
?>
```
find(‘h3.ranking_ttl’)でclass=”ranking_ttl”を取得している。

### 1-3, 計測結果

0.74032497406006
1.5220828056335
2.2691576480865
3.0349636077881
3.8007335662842
4.5622684955597
5.3352293968201
6.1218993663788
6.9005744457245
7.6647825241089
Array ( [0] => メカクシティアクターズ 第3話 「メカクシコード」・・略・・[29] => ダウンタウンDX 2014年5月1日放送分 ) 
平均実行時間: 0.76647825241089
 

## 2, Goutteのベンチマーク

### 2-1, 導入

[GoutteのGitHubページ](https://github.com/fabpot/goutte)から「You can also download the *Goutte.phar* file:」と書いてあるところから、goutte.pharをダウンロードして、作業ディレクトリに配置する。

### 2-2, 実装

```php:
<?php
    require 'goutte.phar';
    use Goutte\Client;
     
    header('Content-Type: text/html; charset=utf-8');
     
    $kNumberOfSamples = 10; // 何回サンプリングするか
     
    $titles = array(100);
    $totalOfTime = 0;
    for ($i = 0; $i < $kNumberOfSamples; ++$i)
    {
        // 計測を開始する
        $startTime = microtime(true);
         
        // ランキングにある全てのタイトルを取得する
        $client = new Client();
        $crawler = $client->request('GET', 'http://say-move.org/ranking.php');
        $rank = 0;
        $crawler->filter('h3.ranking_ttl')->each(function($element)
        {
            global $titles;
            global $rank;
            $titles[$rank] = $element->text();
            ++$rank;
        });
         
        // 解放する
        unset($client);
        unset($crawler);
         
        // 計測を終了する
        $totalOfTime += microtime(true) - $startTime;
         
        echo $totalOfTime . '<br/>';
    }
     
    print_r($titles);
    echo '<br/>平均実行時間: ' . $totalOfTime / $kNumberOfSamples;
     
    unset($titles);
?>
```
PHP初心者なので、ブロック内外でtitlesが二つ存在することになかなか気付きませんでした。

### 2-3, 計測結果

0.57542490959167
1.1356089115143
1.693286895752
2.2634289264679
2.8295919895172
3.4025230407715
3.9880549907684
4.5648419857025
5.1197459697723
5.6885468959808
Array ( [0] => メカクシティアクターズ 第3話 「メカクシコード」・・略・・[29] => ダウンタウンDX 2014年5月1日放送分 ) 
平均実行時間: 0.56885468959808
 
## a. 結論

Goutteのほうが速いです！

メモリも計測したところ、Goutteのほうが少メモリです！
（ただしunsetでは少しメモりが漏れているようです。何か他の解放方法があるかもしれません）

**「どっちがいい？」**
私の結論はGoutteです。