PHPでスクレイピング。phpQueryとphp-simple-html-dom-parserの比較と設置方法
2020/02/08
PHPのスクレイピングのライブラリは「PHP Simple HTML DOM Parser」がオススメ
PHPのスクレイピングのライブラリは「PHP Simple HTML DOM Parser」
PHPでスクレイピングをするならば「PHP Simple HTML DOM Parser」がオススメです。
PHP Simple HTML DOM Parser
https://simplehtmldom.sourceforge.io/
ライブラリのダウンロードは下記の「Source Forge」から。
https://sourceforge.net/projects/simplehtmldom/files/
多くのサイトでは「phpQuery」が紹介されていますが、「PHP Simple HTML DOM Parser」を使うほうがいい理由も含めて「PHP Simple HTML DOM Parser」を紹介いたします。
「phpQuery」より「PHP Simple HTML DOM Parser」をオススメする理由
「phpQuery」に問題があると考える理由
まず、PHPでスクレイピングするために「PHP スクレイピング」と検索してみると、検索結果に表示される上位のページは「phpQuery」に関連する記事で埋め尽くされています。(2020年01月現在。)
そのため、PHPでスクレイピングをするなら「phpQuery」を使うことが一般的なんだな、と思うだろうと思います。
私もそう思いました。
phpQueryのダウンロードページ
https://code.google.com/archive/p/phpquery/downloads
ですが、いざ「phpQuery」を使うためにダウンロード先として提示してある上記のページに遷移してみると、気になることが出てきました。
「Uploaded」の日付が、最新の日付でも「2009年 5月」なのです。
10年以上前に開発されたライブラリが未だに使われているということは、10年前の時点ですでに完成されたライブラリだった、という考え方も可能だろうと思います。
しかし、ここ 10年間で発見されたセキュリティホールに対しては一切対応されていない状況でもあるわけです。
さて、10年以上も前に開発が止まったライブラリを使っても問題ないでしょうか??
「PHP Simple HTML DOM Parser」は継続的に開発が行われている
というわけで、PHPのスクレイピング関連ではほとんどが「phpQuery」の記事であるわけですが、その中で違うライブラリとして登場してくるのが「php-simple-html-dom-parser」なのです。
https://sourceforge.net/projects/simplehtmldom/files/simplehtmldom/
ライブラリ「php-simple-html-dom-parser」を配布している上記 URLを見てみると、現在(2020年01月)でも開発が行われているであろうことを感じることが出来ます。
https://github.com/Kub-AT/php-simple-html-dom-parser
また、上記の Githubで配布されている 2020年01月時点での最新安定版である「Version 1.9.1」では、「PHP 7.3 compatible」と書かれています。
これから新しくスクレイピングのライブラリをインストールするなら、「PHP Simple HTML DOM Parser」を選択すべきではないでしょうか??
また、「phpQuery」と「php-simple-html-dom-parser」を両方使ってみると分かりますが、基本的な使い方は大きな違いはありません。
さらに、「PHP Simple HTML DOM Parser」の方がより便利な使い方ができる関数も用意されているわけですので、「PHP Simple HTML DOM Parser」を選択しない理由がありません。
今回、こんな記事を書いていますが、実は、3年前に「PHP Simple HTML DOM Parser」に関する記事を書いていました。
CakePHP3でcomposerを利用してライブラリ・プラグインをインストールする方法
「PHP Simple HTML DOM Parser」の使い方については触れていませんが、3年くらい前にスクレイピングをするツールを作った記憶がありますので、そのときに使い、記事を書いたのだと思います。
「PHP Simple HTML DOM Parser」の設置方法、使用方法
「PHP Simple HTML DOM Parser」の基本的な設置方法、および、使用方法を紹介します。
1.PHP Simple HTML DOM Parserをダウンロード
PHP Simple HTML DOM Parser
https://sourceforge.net/projects/simplehtmldom/files/
上記の URLにあるソースファイル一式をダウンロードします。
ダウンロードした zipファイルを展開し、「simple_html_dom.php」ファイルを取り出し、ライブラリを読み込むプログラムと同じ階層に配置します。
2.「simple_html_dom.php」ファイルを読み込み
「simple_html_dom.php」ファイルを PHPに読み込みます。
1 2 |
// PHP Simple HTML DOM Parser の読み込み require_once "simple_html_dom.php"; |
3.HTMLファイルをスクレイピング
HTMLのソースコードを取得し、スクレイピングする処理を記述します。
1 2 3 4 5 |
// HTMLファイルを読み込みオブジェクト化します $html = str_get_html( '<html><body>Hello!</body></html>' ); // bodyタグを取得し、text部分を取り出します print_r($html->find("body",0)->plaintext); |
このサンプルでは、「body」タグを取得し、タグに含まれるテキストを表示する処理にしています。
「find(“body”,0)」の「find()」の 1つめのパラメーターが取得するタグの指定で、2つめのパラメータが 1つめのパラメーターで指定したタグの何番目のノード(項目)を取得するかを指定しています。(「0」は「1個目」を指定していることになります。)
2つめのパラメータが抜けている場合は、下記のエラーメッセージが表示されます。
1 |
Notice: Trying to get property 'plaintext' of non-object in C:\xampp\htdocs\scraping.php on line 100 |
4.全体のソースコード
1~3までのソースコードまとめると全体で下記のソースコードになります。
わずか 3行でスクレイピングが出来てしまっているわけです。
1 2 3 4 5 6 7 8 9 |
<?php // PHP Simple HTML DOM Parser の読み込み require_once 'simple_html_dom.php'; // HTMLファイルを読み込みオブジェクト化します $html = str_get_html( '<html><body>Hello!</body></html>' ); // bodyタグを取得し、text部分を取り出します print_r($html->find("body",0)->plaintext); |
URLを指定してスクレイピングをする方法
先の例では、関数「str_get_html()」を使用し、パラメータとして HTMLのソースコードを指定しました。
ですが、「PHP Simple HTML DOM Parser」には、URLを指定して直接 HTMLのオブジェクトを生成する関数「file_get_html()」も用意されています。
この関数を使うと直接 URLを指定してオブジェクトを生成することが出来ます。
1 2 3 4 5 6 7 8 9 10 |
<?php // PHP Simple HTML DOM Parser の読み込み require_once "simple_html_dom.php"; $url = "http://www.metro.tokyo.jp/"; // URLを指定してオブジェクト化します $html = file_get_html($url); print_r($html->find("a",0)->plaintext); |
今回は、サンプルとして「東京都」の URLを指定しています。
「PHP Simple HTML DOM Parser」の「file_get_html()」を使う際のつまづきポイント
実は、「PHP Simple HTML DOM Parser」の「file_get_html()」を使う際には一つのつまづきポイントがあります。
サンプルとして「東京都」の URLを指定していますので、特にエラーが発生することなく正しい情報が取得できているのではないか、と思います。
ですが、「東京都」のサイトから変えて SSL化されている URLを指定すると下記のエラーが表示される場合があります。
ここでは、例として「https://www.yahoo.co.jp/」を指定しています。
1 2 3 4 5 6 7 |
Warning: failed loading cafile stream: `C:\xampp\apache\bin\curl-ca-bundle.crt' in C:\xampp\htdocs\simple_html_dom.php on line 82 Warning: file_get_contents(): Failed to enable crypto in C:\xampp\htdocs\simple_html_dom.php on line 82 Warning: file_get_contents(https://www.yahoo.co.jp/): failed to open stream: operation failed in C:\xampp\htdocs\simple_html_dom.php on line 82 Fatal error: Uncaught Error: Call to a member function find() on bool in C:\xampp\htdocs\scraping.php:100 Stack trace: #0 {main} thrown in C:\xampp\htdocs\scraping.php on line 100 |
1行目にエラーの原因が書かれていますが、SSL証明書が設定されていないためエラーとなっています。
SSL証明書がしっかり登録されているサーバであれば問題ありませんが、私のように XAMPPを使って実験しているような場合は対応が非常に難しくあります。
こうなる理由は、「simple_html_dom.php」の中を見てもらえば分かりますが、「file_get_contents()」でサイトにアクセスしているためです。
cURLで Webサイトにアクセスをして PHP Simple HTML DOM Parserを利用する方法
というわけで、関数「file_get_html()」に URLを指定してスクレイピングをするためのオブジェクトを生成する方法は、SSLに対応したサイトでは利用できませんので、何らかの対応を行う必要がありますが、そんなときに利用する方法として cURLがあります。
cURLを利用して HTMLを取得し、取得した HTMLを「str_get_html()」で処理をする、という方法です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
<?php // UserAgent define("USER_AGENT_TEXT", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"); // PHP Simple HTML DOM Parser の読み込み require_once "simple_html_dom.php"; $url = "https://www.yahoo.co.jp/"; $htmlSource = getApiDataCurl($url,"html"); $html = str_get_html( $htmlSource ); print_r($html->find("a",0)->plaintext); // APIを呼び出し、結果を受け取る処理(URLにアクセスしその結果を取得する処理) // $url :APIの URI(アクセスする URL) // $responseType:受け取る結果のタイプ(header、html、json) function getApiDataCurl($url, $responseType = "html" ){ if ( $responseType == "header" ) { $option = [ CURLOPT_RETURNTRANSFER => true, // 文字列として返す CURLOPT_TIMEOUT => 3000, // タイムアウト時間 CURLOPT_HEADER => true, CURLOPT_NOBODY => true, CURLOPT_SSL_VERIFYPEER => false, // サーバ証明書の検証をしない ]; } else { $option = [ CURLOPT_RETURNTRANSFER => true, // 文字列として返す CURLOPT_TIMEOUT => 3000, // タイムアウト時間 CURLOPT_SSL_VERIFYPEER => false, // サーバ証明書の検証をしない CURLOPT_USERAGENT => USER_AGENT_TEXT, // UserAgentを指定 ]; } $ch = curl_init($url); curl_setopt_array($ch, $option); $body = curl_exec($ch); $info = curl_getinfo($ch); $errorNo = curl_errno($ch); $errorMsg = curl_error($ch); // 「CURLE_OK」以外はエラーなのでエラー情報を返す if ($errorNo !== CURLE_OK) { // 詳しくエラーハンドリングしたい場合はerrorNoで確認 // タイムアウトの場合はCURLE_OPERATION_TIMEDOUT return $errorNo . " : " . $errorMsg; } // 200以外のステータスコードは失敗なのでそのステータスコードを返す if ($info['http_code'] !== 200) { return $info['http_code']; } // headerのみ取得 if($responseType == "header") { $responseArray = explode("\n", $body); // 行に分割 $responseArray = array_map('trim', $responseArray); // 各行にtrim()をかける $responseArray = array_filter($responseArray, 'strlen'); // 文字数が0の行を取り除く $responseArray = array_values($responseArray); // キーを連番に振りなおす // HTMLの本体を取得 } elseif($responseType == "html"){ $responseArray = $body; // JSONで取得した情報を配列に変換して取得 } else { $responseArray = json_decode($body, true); // JSON を配列に変換 } return $responseArray; } |
なぜ cURLを使う方がいいのか、また、上記の cURLの関数の解説などの cURLについて「PHPのcURLでAPIやWebサイトへのアクセス方法。file_get_contentsとの比較」の記事を書いていますので、合わせて確認をしてください。
また、「PHP Simple HTML DOM Parser」の詳しい使い方や、サイトによっては気をつける必要がある場面の解説などについて下記に記事を書きました。併せて確認をしてください。
PHPのスクレイピングライブラリ「PHP Simple HTML DOM Parser」の使い方
また、「PHP Simple HTML DOM Parser」を CakePHP3で使うときの設置方法については下記に記事を書きました。
CakePHP3でPHP Simple HTML DOM Parserを使ってスクレイピングする方法
スクレイピングとスキャルピング
プログラムとは関係ありませんが、いつも「スクレイピング」と「スキャルピング」とがごちゃごちゃになります。
どっちがどっちか、どうやって覚えたらいいでしょうか??
「スキャルピング」とは、FX(Foreign Exchange。外国為替証拠金取引。)や株式取引において、薄利の取引を短時間で数多く繰り返すトレーディング手法のことです。
「スキャルピング(scalping)」のもとの意味は「皮むき」で、りんごなどの皮をむくように薄い利益を取っていく手法であるためにこの名前が付いています。
また、スクレイピングは「scrape(スクレイプ、削る)」の「ing形」です。
「scrap(スクラップ、切れ端、小片、解体する)」とは関係がないようです。
GoogleAdwords
GoogleAdwords
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!
関連記事
-
ECCUBEの注文完了画面注文番号と商品情報を編集するCRITEO(クリテオ)タグを編集
ECCUBEの注文完了画面にクリテオのタグを編集する方法を紹介。標準機能では完了画面に注文IDや購入商品の情報を渡さないため改修が必要です。
-
PHPで特定の日間の日付を for、strtotimeで表示する
ある特定の間の日付の情報を for文、strtotimeを使って作成し、その解説をしています。
-
ECCUBEでアップロードできない。upload_max_filesizeを設定する場所
テンプレートをアップロードする際に発生するエラー「テンプレートファイルがアップロードされていません」の対処方法。これはファイル容量の制限に引っかかっています。
-
フォルダを指定してファイルのパーミッションを変更するプログラム
フォームからフォルダ、パーミッションを指定しパーミッションを変更するサンプルプログラムの解説です。
-
ECCUBEのポイント設定、ポイント付与率を一括で変更する方法解説
ECCUBEの商品個別に設定してあるポイントを一括で変更する方法を解説。ECCUBEには商品個別のポイントを一括して変更する機能がありません。SQLを作成して一括置換!
-
複数銘柄を指定して株価チャートを一覧するツール公開
入力銘柄の5日間、3か月間、6か月間、1年間、2年間の株価チャートを一覧表示しますのでチャートで売買判断をするのに最適です。
-
連想配列のキーも値もまとめてhtmlspecialchars()でサニタイズする関数の作成解説
PHPの配列・連想配列のキーと値をまとめてhtmlspecialchars()関数でサニタイズ(無害化、無毒化)を行う関数を作成。連想配列のキーはarray_map()関数でのサニタイズは無理。
-
Smartyのテンプレート内の処理で計算、加工をする方法
Smartyのテンプレート上で変数を計算する、加工する方法を解説します。
-
Smartyの修飾子regex_replaceで正規表現の後方参照・PHPではpreg_replace
ECCUBEで使われているSmartyで文字列を正規表現で置換し後方参照で値を利用する装飾子regex_replaceの解説です。細かな条件がありますので注意が必要です。
-
配列の値をテキスト表示する際に「、」でつなげるときの処理方法の一例
配列の値を「、」でつないで出力する際、単純にforeachで繰り返し処理をすると「イヌ、サル、キジ、」となるが文字列最後の「、」を出力しない方法を3つ解説している。
Comment
初めまして。突然のメッセージ失礼いたします。
現在、情報を集めるWebページを作り、自サイトの更新を簡単に使用と考えてスクレイピングを考えており、phpQueryでどうしても取得できず、こちらにたどり着き、simple html domでかつ、curlを利用したもので取得することができ必要な情報はechoで確認できている状態です。
しかし、アクセスを海外からする必要がある場合があり、proxyをかませたいと考えているのですがgetApiDataCurl関数にproxyを入れることができず困っております。(curlは全く分かりません(泣))
お時間がございましたら、教えていただければ幸いです。
sonicpepe(:HN)さん、コメントありがとうございます。
cURLでプロキシを経由してサイトにアクセスをする場合は、オプションとしてプロキシ接続の設定を追記します。
オプション設定として「$option2」の配列として設定します。
それを、「array_merge()」関数でマージします。
もともとの「$option」配列に直接追記する方法でもかまいませんが、関数の中ですので、別配列として持ち、関数のパラメータなどで必要に応じて組み込むと言った方法がいいのではないかと思います。
ただし、このソースは全く検証していませんので、その点はご了承ください。