読者です 読者をやめる 読者になる 読者になる

備忘録

なんとなく暇なときにでも....

指定したWebページにログインしてスクレイピングを行う

やってみた php

先日の記事でネイティブのPHPだけでWebページのスクレイピングを行いました。

hchckeeer.hatenadiary.jp

このままでももちろんスクレイピングを行うことはできます。
しかしもし、仮にログインしていた時と未ログインの場合で表示情報が異なる場合、しかも実際にスクレイピングをしたいのがログインした時に表示される情報であるとき。
こんなときは、クローラーに自動でログインをさせたい。(しかし、まずそんなことってできるのか自体疑問でした。)
ぐぐってみたら情報自体はちょこちょこ落ちてました。なんでも、curlを使ってログインできるとのこと。(普通に考えれば、ごもっともな話ですが、若輩者ですのでご勘弁を。)

流れ自体としては、以下のような形。

  1. ログインページで移動。このとき指定した(ログインページ)のWebページから発行されたクッキーを受け取って、保存。

  2. ログイン情報をcurlにset_optし、それらをPOST。

  3. スクレイピングを行うページごとに保存したクッキーを読み込んでからスクレイピングを行い、データを適宜抽出する。

適宜必要な部分だけを抜き出したソースはこちら↓

//クッキーを保存するファイルを適宜作成
$file_path = tempnam(sys_get_temp_dir(),'cookie_');

// 1.
public function move_login_page($file_path)
{
    $ch = curl_init();
   //ログインページのURLを指定
    curl_setopt($ch, CURLOPT_URL, self::LOGIN_PAGE_URL);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
   //サーバーで発行されたクッキーを $file_path に書き込む
    curl_setopt($ch, CURLOPT_COOKIEJAR, $file_path);
    $put = curl_exec($ch) or dir('error ' . curl_error($ch));
    curl_close($ch);
        
    return;
}

// 2.
public function login($file_path)
{
    $params = array(
         "name" => 'hoge_name',
         "password" => 'hoge_pass',
    );
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, self::POST_URL);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   //リダイレクトされてしまう場合があるので、リダイレクト先を追跡するようにする。
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_COOKIEFILE, $file_path);
    curl_setopt($ch, CURLOPT_COOKIEJAR, $file_path);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
    $output = curl_exec($ch) or dir('error ' . curl_error($ch));
    curl_close($ch);

    return ;
}

// 3.
public function get_scraped_data($url,$pass=NULL)
{
    $ch=curl_init();
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
   //読みんだクッキーを使用して、ログイン状態を保持する。
    curl_setopt($ch,CURLOPT_COOKIEFILE,$file_path);
    curl_setopt($ch,CURLOPT_COOKIEJAR, $file_path);
    curl_setopt($ch,CURLOPT_FOLLOWLOCATION,true);
    $html=curl_exec($ch);
    curl_close($ch);
    if( !$html ){
        return NULL;
    }
    
   //読みこんだ要素を配列化する。
    $dom = new DOMDocument();
    @$dom->loadHTML($html);
    $xml = simplexml_import_dom($dom);
    if( isset($pass) ){
        $div = $xml->xpath($pass);
        $json = json_encode($div);
    }else{
        $json = json_encode($xml);
    }
    return json_decode($json,true);
}

今回のポイントは

curl_setopt($ch,CURLOPT_COOKIEFILE,$file_path);
curl_setopt($ch,CURLOPT_COOKIEJAR, $file_path);

でしょうか。クッキーを管理して、curlを叩くときに、管理しているクッキー情報も一緒に飛ばして、常にログイン状態を維持しているみたいですね。

ログイン時にPOSTする情報は

$params = array(
         "ame" => 'hoge_name',
         "password" => 'hoge_pass',
    );

で指定している。はてなのログイン画面を例にしてみます。

f:id:tomAn:20160820040634p:plain

htmlとかphpとかを使って簡単なwebページを作った方ならおわかりかもしれませんが、各情報を入力しているテキストフィールドのhtml部分のタグの"name"要素で指定しています。つまり、array(" 指定要素の"name" " => "入力要素" );ということである。 またPOST_URLはformタグのactionの内容を指定することになる。
これで実際にログインができているはず。あとはそこで使用したクッキーをしっかりと管理しつつ、ログインを維持して、スクレイピングを行うことができます。


本日はここまで。


本日の更新部分も含めてgithubにあげております。
github.com

参考

PHP:クッキーが必要なサイトをスクレイピングする方法 その3 – マイヤーの開発ブログ

メモ: [PHP][cURL] PHPのcURLを使ってGoogleにログインする

メモ: [PHP][cURL] cURLでクッキーを送受信する

メモ: [PHP][cURL] cURLでリダイレクトをたどるようにする

http://web-prog.com/php/curl-login-scraiping/