nearproの日記

特に意味はありません。主に読んだ本をただただ記録します。

別々のGoutte\ClientにCookie情報を引き継いで渡したい

テストやスクレイピングで便利なGoutteですが、普通に使ってる場合だとCookieとかも宜しく処理してくれるので特に何も考えずにゴリゴリ実装できます。

例えば、ログインが必要なページにアクセスする場合、下のようなコードでログイン後にリクエストします。そしたら、当然、ログイン画面にリダイレクトされることもなくページを取得できます。

<?php
$client = new Goutte\Client();
$crawler = $client->request('get', 'http://www.facebook.com'); //ログインページ
$form = $crawler->filter('#login_form')->form();
$form['email'] = 'hogehoge@gmail.com';
$form['pass'] = '****************';
$client->submit($form); //ログイン

//ログインが必要な適当なページにアクセス
$crawler = $client->request('get', 'https://www.facebook.com/events/upcoming');

echo $crawler->filter('title')->text(); // イベント

しかし、こういったログインと取得を分けて実装したいこともあると思います。(並列で処理したかったり、画面遷移を含むWebアプリ上で使いたかったり) そんなとき、毎度毎度、『ログインして取得』というコードを書くのもアレだし、セキュアなサービスだとログインする度に排他処理が走り、並列に処理しようと思ったら『別のPCからログイン…』うんぬん言われる可能性もあるし。。。ということで、そういうときはCookie情報を渡せば良いんじゃないかと思います。

イメージ的にはブラウザで複数のタブを開いてる感じですね。

ということでコード。

下のように書くと、もちろんログインページにリダイレクトされてしまう。

<?php
$client = new Goutte\Client();
$crawler = $client->request('get', 'http://www.facebook.com');
$form = $crawler->filter('#login_form')->form();
$form['email'] = 'hogehoge@gmail.com';
$form['pass'] = '****************';
$client->submit($form);

$client = new Goutte\Client();  //新しいクライアント
//ログインが必要な適当なページにアクセス
$crawler = $client->request('get', 'https://www.facebook.com/events/upcoming');

echo $crawler->filter('title')->text(); //Facebookにログイン | Facebook

下のようにクッキーを保存して渡してあげれば、ログイン処理を再度しなくともリダイレクトされない。

<?php
$client = new Goutte\Client();
$crawler = $client->request('get', 'http://www.facebook.com');
$form = $crawler->filter('#login_form')->form();
$form['email'] = 'hogehoge@gmail.com';
$form['pass'] = '****************';
$client->submit($form);
//クッキーを保存しておく
$cookies = $client->getCookieJar()->all();

$client = new Goutte\Client();  //新しいクライアント
//保存してたクッキーをセットする
$client->getCookieJar()->updateFromSetCookie($cookies);
//ログインが必要な適当なページにアクセス
$crawler = $client->request('get', 'https://www.facebook.com/events/upcoming');

echo $crawler->filter('title')->text(); // イベント

ちなみにFacebookなど今風のWebは大抵jsを駆使して非同期に読み込んだりしているので、直接jsonを取りに行くとかしないとほとんどスクレイピングも何もできない。そういうサービスは大抵APIとか用意してるので別に困ることも少ない。

ただ、稀にどうしてもスクレイピングする必要があるケースもある。そうした時は、phantomJSを使ったほうが楽。

phantomJSでCookieを引き継ぎ引き継ぎ色んな所にアクセスする方法は、また気が向いたらまとめます。