やりたかったこと
Goutteで某サイトへログイン、リンクを辿ってCSVファイルをダウンロードする。
以前やったし楽勝だろうと思っていたが、思いの外ハマったので記事にしときます。
読むと分かること
POSTでリンクらしきものを叩き、叩いた結果からCSVを取得する実装方法
(↑本記事とはあまり関係ないですが、POSTになるのは、
内部的にはJavaScriptとかが呼ばれてhiddenでもろもろの値を設定してから、検索したりしているためです)
環境
CentOS release 6.8 (Final)
PHP 5.4.34
Goutte v2.0.4
(いろいろちょい古いです)
Goutteでのダウンロード
- ぐぐるとよくある例
$client->request('GET', 'http://hoge.com/download.php');
$client->request('GET', 'http://hoge.com/download.csv');
あと、以前私が書いた記事
http://qiita.com/kokushi_yayoi/items/299f62b8fece8b1920d6
違う、今回はPOSTでダウンロードしたいのだ
実装方法
下記のように実装したところ、今回はPOSTのレスポンスからCSVのテキストを取得できました
<?php
require_once __DIR__ . "/goutte-v2.0.4.phar";
use Goutte\Client;
$client = new Client();
/*** もろもろ略 ***/
/*** CSVダウンロードボタンのページまでは実装済みで遷移済みです ***/
$result = $client->submit($csv_download_form);
// POSTのレスポンスを取得してます
$csv_download_response = $client->getResponse()->getContent();
// 念のため、読み込みできるかを確認
if ($csv_download_response->isReadable()) {
$directory_path = './download/';
// ここにCSVのデータを全部入れてます。
// read()でレスポンスを読み込むができ、getSize()で結果が何文字だったかが分かるので、全部読み込みしてます
$response_content = mb_convert_encoding($csv_download_response->read($csv_download_response->getSize()), 'utf8', 'sjis-win');
$file = new SplFileObject($directory_path.'hoge.csv', 'w');
$file->fwrite($response_content);
} else {
echo '読み込みできませんでした';
}
答えを見ればけっこうかんたんです。
ただ、ググっても良い感じの情報にたどり着くのに時間がかかりました。
調査した順序
- ログインしてCSVダウンロードの手順は手動で行い、開発ツールを使って、要素を洗い、何が行われているかを調べながら進めます。
- 調べた要素通りにログイン→ページ遷移→CSVダウンロードボタン押下までを実装します。上に挙げた以前の記事をご覧ください。
- 普通にダウンロードボタン押下まではかんたんに実装できた。以前の通りにCSVに書き出そうとしたら、うまく書き出されない。
- 開発ツールでNetworkパネルで調べたところ、今回のサイトはPOSTしていて、以前と同じ実装(GETのレスポンスをゴニョゴニョする)は通用しないことが判明。
- とりあえずググるがよくわからないので、地道にNetworkパネルの中身を読み込んで、var_dump()で何が取れているかを確認。
- Response HeadersのContent-Dispositionにちゃんとデータが入っていることは確認できたので、ドキュメントにあったread()とgetSize()で当たりをつけて実装してみたら動いた。
答えが載っているドキュメント。
http://docs.guzzlephp.org/en/5.3/streams.html
$client->getResponse()をvar_dumpするとわかりますが、
contentの中にStream型で入っています。
結論
無事POSTで取得するパターンのCSVファイルも取得できました。
スクレイピングをしていると、普段あまり意識していない
RequestとResponseで各項目が何を意味してどういう情報が入っているかを
詳細に知る必要があるのでいい勉強になります。
特に開発ツールのNetworkパネルはめっちゃ有用な情報が詰まってるので、
一度眺めてみると面白いかもしれません。