Diggin_Scraperでは、スクレイパーのインスタンスを生成後、processメソッドに抽出方法をセットします。 processメソッドには、多種多様な抽出方法が指定可能ですが、ここでは、Diggin_Scraperがデフォルトで用意している指定方法について解説します。
第二引数以降には、その抽出対象のプロパティ名(任意)と取得型(「表示されている文字列」として、「HTMLソース文字列」としてあるいは「取得したSimplexmlそのまま」かなど)、そして必要であればフィルタ名を以下のようにすべて文字列として囲みます。
$scraper = new Diggin_Scraper();
$scraper->process('//p//a', 'list[] => text, Digits')
//->process('抽出要素', 'プロパティ => 取得型, フィルタ名')
->scrape('http://example.net/');
上記において、「=>」はプロパティ名と取得型を分ける区切り文字列、またそれ以降のカンマ(,)は取得型とフィルタ名を分ける区切り文字列として処理されます。 取得した要素は、スクレイパーオブジェクトのresultsプロパティに全てそのキーに対するリストとして格納されます。'[]'をプロパティ名の後ろに記述しなかった場合、取得された最初の要素一つがプロパティキー名に対する連想配列として格納されます。 また各キー要素は、マジックメソッド__getの利用により、スクレイパーオブジェクトのプロパティとして取得することも可能です。つまり上記の"list"プロパティを指定した場合、scrapeメソッド実行後は、以下のように取得することが可能です。
$results = $scraper->getResults(); $results['list'];
//あるいは
$scraper->list;
もっとも一般的な取得型は"TEXT"というHTMLソース文字列での取得と、"@href"といった"@属性値"での取得です。属性を指定した場合において、 '@href'と'@src'だった場合は相対パスから絶対パスへと自動変換されます。
フィルタは、取得された各値に対しフィルタリング処理を行います。フィルタリングは「ユーザー定義関数」・「Zend_Filter」・「ユーザ定義フィルタクラス」の順に存在チェックをし処理がコールされます。フィルタはカンマ区切りにより複数指定可能です。上記の"list"プロパティの場合、アンカー文字「RFC 2606」に対し、Zend_Filterの'Digits'フィルタが適用され「2606」という数値を保持したリストが格納されることになります。
スクレイピングの実行は、 scrapeメソッドをコール時に行われます。scrapeメソッドには対象となるサイトのURLを指定します。
demos/Diggin/Scraperに格納してあるスクリプト群にて実際の使用例を確認できます。
* スクレイパーからリクエストを送信する際は、各サイトの使用許諾をご確認ください。
標準で使用される取得型は以下の通りです。
| 取得型 | 説明 |
|---|---|
| raw | 指定要素をそのままオブジェクトにて返却します。SimpleXMLを使用する場合に便利です。 |
| asxml | 単純に指定された要素をSimplexmlのasXml()メソッドにて取得し返却します。 |
| text | 指定対象のHTML文字列からテキスト部分を取得します。 |
| html | 指定対象のHTML文字列からテキスト部分を取得したあと、外側のタグを削除します。 |
| plain | rhacoのSimpleTagにおける’PLAIN’に近いテキスト取得を行います。 |
| @"属性" | 指定対象に対応する「@"属性"」の値を取得します。(@href, @srcについては絶対パスへの変換も行います。) |
| 0.7では、属性がセットされてない場合nullが格納されます。 |
取得型は、0.6まではDiggin_Scraper_Strategy_*のgetValue()、0.7では各Diggin_Scraper_Evaluator_Abstractを継承した各クラスにあるメソッドにて定義されています。
Http経由でのスクレイプは、デバッグの度にhttpリクエストが発生していてはいけません。デバッグのための、方法をここに提示します。
Diggin_ScraperのスタティックメソッドsetHttpClientには、Zend_Http_Clientのインスタンスを指定できます。
$test = new Zend_Http_Client_Adapter_Test;
$client = new Zend_Http_Client(null, array('adapter' => $test));
Diggin_Scraper::setHttpClient($client);
Diggin_Scraperのインスタンスをnewする前に、上記のようなテスト用コードを挿入します。 詳しくは、Zend Frameworkのテストアダプタの項目を参照してください。
上の方法でも時に億劫に感じることでしょう。Diggin_Scraperのscrapeメソッドにて、第一引数に配列が渡された場合、Zend_Http_Responseオブジェクトへと変換が行われます。(ヘッダーが指定されてない場合は、200レスポンスが架空に設定されます。)
$html = '<html><body></body></html>'
$scrpaer = new Diggin_Scraper;
$scrape->scrape(array($html)); //レスポンスボディ(html)をarrayにて渡します。
Diggin_Scraperからリクエストを発行した場合には、レスポンスステータスが成功でない場合(Zend_Http_ResponseのisSucces()メソッドにて判定します)は、Diggin_Scraper_Exceptionをスローします。もし、ステータスの有無に関わらずスクレイプ対象にしたい場合、スクレイパーオブジェクトのscrapeメソッド引数にZend_Http_Responseのオブジェクトを渡します。
Diggin_Scraperでは、scrapeを実行するプロセスの抽出要素に該当するものが無かった場合Diggin_Scraper_Strategy_Exception例外を投げます。ただし、多次元配列取得用にセットされたプロセス分については、値が格納されません。(数値添字配列から該当のキーがスキップされたものになります。) これは、該当対象が無かった場合に継続の処理ができないという判断によるものです。コンストラクタにて、この例外を投げないよう変更できます。Web::Scraperでは、該当対象が無かった場合ブランクが格納されます。この仕様の相違については現在標準で例外を投げないよう検討しています。