とあるサイトから、設定した条件で生成されるcsvデータを取得するという処理を書いたんだが、
予想外にハマったのでメモ。
個人的メモなのでわかりやすく書いてません。あしからず。
- 証明書を設定
IEなどでサイトから取得した証明書は.pfxになっている。
今回はそもそもIE以外のブラウザ(UA)は受け付けないサイトだった。
そのため、サーバ側でPEMに変換。
openssl pkcs12 -in hoge.pfx -out hoge.pem
IEでは「ツール」-「オプション」-「コンテンツ」タブに証明書ボタンがあるので、そこからエクスポートする事で取得できる。
秘密キーもエクスポートする。
できたファイルをサーバ上の適当なディレクトリに配置する。
あくまでも”設置するに適当”な場所へ。
- cURLによる接続
今回https://だったので、cURLとなった。
HTMLの取得自体は以下でOK。
$_curl = curl_init(); curl_setopt($_curl, CURLOPT_URL, $url); $html = curl_exec($_curl);
これに様々なcurl_setoptをかましていく。
配列形式でもOK
証明書の設定は以下
curl_setopt($_curl, CURLOPT_SSLCERT, 'hoge.pem'); curl_setopt($_curl, CURLOPT_SSLCERTPASSWD, 'password');
passwordはエクスポート時に設定したもの。
これで認証を通過する。
オレオレ証明書を無視するオプションもあり。
curl_setopt($_curl, CURLOPT_SSL_VERIFYPEER, FALSE);
実際にはCookieなども。
curl_setopt($_curl, CURLOPT_COOKIESESSION, TRUE); curl_setopt($_curl, CURLOPT_COOKIEFILE, 'cookie.txt'); curl_setopt($_curl, CURLOPT_COOKIEJAR, 'cookie.txt');
いずれもパスはフルパスで記述。
また、htmlを取得するのが目的なため、以下も設定
curl_setopt($_curl, CURLOPT_RETURNTRANSFER, TRUE);
その他にも沢山のオプションがあり、ヘッダ出力や進捗状況の表示をするオプションはデバッグ時に設定しておきたい。
curl_setopt($_curl, CURLOPT_HEADER, TRUE); curl_setopt($_curl, CURLOPT_NOPROGRESS,TRUE);
- POST
実際のスクレイピングでは、一発で目的とするhtmlやデータを取得する事は難しく、
ログイン処理やパラメータの設定を経て、csvのダウンロードなどに辿りつける事がほとんど。
cURLはいちいち
curl_init(); curl_close($_curl);
を繰り返さなくても、取得したリンクURLから
curl_setopt($_curl, CURLOPT_URL, $url); $html = curl_exec($_curl);
でブラウザでの画面遷移と同様にコネクションをRE-Usingしてくれて、目的の画面まで到達できる。
分かりやすい。
で、POSTするデータだが、マニュアルには文字列でも配列でもOKと書いてある。
ただ実際には、配列で渡すとサイトに通知されない場合があるようで、今回この現象で数日を棒に振った。
テストプログラムを書いて実験してみても、普通に通知されるので「???」だったが、何かの要因で配列で渡すとサイト側にわたらなくなるようだ。
とここまで書いて思ったが「Content-Typeヘッダにはmultipart/form-dataを設定します。」とか書いてあるし…
これって、php側で勝手に設定されるという意味かと思ってた…orz
ヾ(@^▽^@)ノ
$data = array( 'param1' => '', 'param2' => '', 'param3' => '', 'param4' => '', 'param5' => '', ); foreach($data as $k => $v){ $params[] = $k.'='.urlencode($v); } curl_setopt($_curl, CURLOPT_POST , true); curl_setopt($_curl, CURLOPT_POSTFIELDS , implode("&",$params));
こんな感じで、無理矢理文字列に変換して渡す事で解決。
で、取得したhtmlからpreg_matchなどを行なって目的とするURLを取得し、
それを繰り返して最終的なhtml(またはデータ)まで到達する。
ただし、取得したhtmlにそのまま目的とするURLが記載されているとは限らないので、
FireBugなどの開発ツールを用いて行う必要がある。