~2回戦~ PHPでスクレイピング【Goutte vs. PHP Standard APIs】

1回戦、 **Goutte** は Simple HTML DOM Parser  相手に、平均0.2s程度の差をつけて、勝利しました。（参考：[PHPでスクレイピング【Goutte vs. Simple HTML DOM Parser】](http://qiita.com/soarcreator/items/56a971d42b8b640b76a6)）

勝利を称える声の中、ある強者の噂を私は耳にしました。

**[引用]機能性ではちょっと劣りますが、パフォーマンス最優先ならpreg_match 関数PHPネイティブの DOMこういった選択肢もアリでしょうね。**

たしかに。パフォーマンスを比べるならば、間違いなくオリジナルの関数の速度に勝つ事はないでしょう。
ですが、私のような初心者が組んだ一例として、Goutteの速度を上回ることが難しい例を紹介します。

そこで、２回戦として、 **Goutte** vs. **preg_match** vs. **DOM** でパフォーマンスバトルを行います。

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



## 0, Goutteのベンチコート

時間帯によって差が生まれるので、今回も計測しなおします。
ソースコードはこの前と同じソースコードを使用します。
(参考: [gist.github.com/soarcreator/11494901#file-file1-php](https://gist.github.com/soarcreator/11494901#file-file1-php))

平均実行時間: 0.57205934524536　でした。

## 1, preg_matchのベンチコート

### 1-1, 実装

```php:
<?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_contents('http://say-move.org/ranking.php');
        if (preg_match_all('/<h3[\s]class="ranking_ttl"><[^>]*>(.*?)<[^>]*><\/h3>/s', $html, $elements))
        {
            $rank = 0;
            foreach ($elements[1] as $title)
            {
                $titles[$rank++] = $title;
            }
             
            // 解放する
            unset($elements);
            unset($title);
        }
        else
        {
            echo 'Not Found';
        }
         
        // 計測を終了する
        $totalOfTime += microtime(true) - $startTime;
         
        echo $totalOfTime . '<br/>';
    }
     
    print_r($titles);
    echo '<br/>平均実行時間: ' . $totalOfTime / $kNumberOfSamples;
     
    unset($titles);
?>
```
正規表現わからないなりに頑張りましたが、効率が悪かったら、すいません。

### 1-2, 計測結果

0.69346404075623
1.3898799419403
2.0906138420105
2.7815208435059
3.479859828949
4.1586039066315
4.8545868396759
5.5568058490753
6.2275168895721
6.9227838516235
Array ( [0] => 【映画】THE GREY 凍える太陽　（吹替え）・・略・・[29] => ブラマヨとゆかいな仲間たち アツアツっ ) 
平均実行時間: 0.69227838516235

なななんと！
PHPのスタンダード正規表現APIが、Goutteより遅いことがわかりました！

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

### 2-1, 実装

とりあえず、途中まで実装しましたが、

```php:
<?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 = new DOMDocument();
        $html->loadHTMLFile('http://say-move.org/ranking.php');
         
        // 計測を終了する
        $totalOfTime += microtime(true) - $startTime;
         
        echo $totalOfTime . '<br/>';
    }
     
    print_r($titles);
    echo '<br/>平均実行時間: ' . $totalOfTime / $kNumberOfSamples;
     
    unset($titles);
?>
```

### 2-2, 計測結果

この時点で、

0.69660210609436
1.3984050750732
2.1059851646423
2.8011412620544
3.4911031723022
4.1912860870361
4.9223821163177
5.6201391220093
6.3140251636505
7.0278391838074
Array ( ) 
平均実行時間: 0.70278391838074

と遅いので、以降実装をするのをやめました。

## a. 結論

私の書いたコードではGoutteがとりあえず速かったのですが、当然GoutteはStandard APIで実装されていますから、もっと頑張れば必ずStandard APIが勝利するでしょう。

Goutteが内部で何をしているかは、本記事では、明らかにしませんが、オープンソースなので、ダウンロードすれば読むことができます。

Goutteのダウンロード＆導入方法などは[一つ前の記事](http://qiita.com/soarcreator/items/56a971d42b8b640b76a6)に書いてあります。よろしければお読み下さい。