楽天RMSログイン処理をPHPのGoutteで組んでみたけど意味がなかった

楽天RMSログイン処理をPHPのGoutteで組んでみたけど意味がなかった

ログイン処理だけなら結構簡単に実装できます。
でもGoutteでサイト内を追っていこうとすると、すぐに限界が来ました。

何をやっても『認証エラーページ』に飛ばされる

しっかり読み込んでから動かせばいいかもとSleepを活用するけどダメ。
ここまでダメだと単純なaタグのような装いをしつつJSで何かの値をPOSTしているのだろうと...。

と言う事で、下に各コードは直接的に使える代物ではありません。
ただ、Goutteの基礎的な使い方として備忘録になるかなと思い記しておきます。

楽天RMSログイン処理

use Goutte\Client;

/*------------------------------------- 
 * ログインしてから処理する 楽天スクレイパー
 *-------------------------------------*/
  /* 窓口 */
  public static function getTester()
  {
      $shop = Shop::find(1);
      $centralcenter = \App\Models\Centralcenter::find(4);
      #Goutteバージョン
      self::getItemAccessData($centralcenter,$shop);
      
      #ヘッドレスchromeバージョン
      #※値を渡しているとなると実ブラウザ操作をエミュレートするしかないので
      #self::headLessChrome($centralcenter,$shop);
        
      return;
  }
    
  /* 動作の分類機 */
  public static function getItemAccessData($centralcenter,$shop)
  {
      #ログインページ用意
      $loginURL = 'https://glogin.rms.rakuten.co.jp/?sp_id=1';
      #ID/PASS用意
      $firstID = hogehoge;
      $firstPass = fugafuga;
      
      #ログイン処理動作を組み立てたFunctionへ
      $logined = self::R_FirstLogin(loginURL ,firstID ,firstPass,secondID,secondPass)      

      #[$logined]の値でログイン処理の成功を判断
      if(!empty($logined)){
          $client = $logined[0];
          $crawler = $logined[1];

          //クッキーを保存しておく
     $cookies = $client->getCookieJar()->all();
          //保存してたクッキーをセットする
          $client->getCookieJar()->updateFromSetCookie($cookies);
          //ログインが必要な適当なページにアクセス
          $crawler = $client->request('GET', 'https://mainmenu.rms.rakuten.co.jp/?left_navi=33');
          # ?left_navi=[番号]でJUMPするページは素直に遷移する
          # これらのページはクッキーを渡さなくても遷移できる
 
          #ページが表示しきるのを待つ
          Sleep(5);

          /* ----------
           * 直接URLを渡して遷移指示しする方法
           * ※cookieを渡しても認証エラーページに飛ばされる
           * ----------*/
          #cookie取得
          $cookies = $client->getCookieJar()->all();
          $client->getCookieJar()->updateFromSetCookie($cookies);
          $crawler = $client->request('GET', 'https://rdatatool.rms.rakuten.co.jp/rdreport/?app=item_basket');


          /* ----------
           * aタグのID値でリンクを探しクリック操作で遷移させる方法
           * ※これも cookieを渡しても認証エラーページに飛ばされる
           * ----------
           * 
           * $cookies2 = $client->getCookieJar()->all();
           * $link = $crawler->filter('a')->filter('#mm_sub0304_05')->link();
           * $client->getCookieJar()->updateFromSetCookie($cookies);
           * $crawler = $client->click($link);
           */
          
          #遷移ページのHTML情報を変数に設置
          $html = $crawler -> html();
          #遷移ページ情報をログに出力  
          Log::info($html);
        }else{
            return;
        }      
  }
  /* 店舗認証 */
  public static function R_FirstLogin(loginURL ,firstID ,firstPass,secondID,secondPass)
  {
      #引数初期化
      $logined = NULL;

      #ログインページ用意
      $loginURL = 'https://glogin.rms.rakuten.co.jp/?sp_id=1';
      #Goutte 実行
      $client = new Client();
      #情報取得
      $crawler = $client->request('GET',$loginURL);

      #検索文字列の登録
      $login_form = $crawler->selectButton('次へ')->form();
      #1stID/PASSを受渡す  
      $login_form['login_id'] = $firstID; //nameを指定
      $login_form['passwd'] = $firstPass; //nameを指定
      $client->submit($login_form);
      #次へボタンをクリック
      $crawler = $client-> click($login_form);
      
      #2ndはログインボタンが出てくるので、コレをフラグにするエラー分岐
      if(empty($crawler ->selectButton('ログイン')->form())){
         return; 
      }else{
         #2段階認証の時スルー
         if(!empty($crawler ->selectButton('ログイン')->form())){
            $logined = self::R_SecondLogin($client,$crawler,secondID,secondPass);
         }else{
            #全てのルートを使っても跳ねられたら終了する
            return;
         }
        return $logined;
      }
  }

  /* ユーザー認証 */
  public static function R_SecondLogin($client,$crawler,SecondID ,SecondPass )
  {   
      $Second_form = $crawler ->selectButton('ログイン')->form();
      $Second_form['user_id'] = $SecondID;
      $Second_form['user_passwd'] = $SecondPass;
      $crawler = $client-> click($Second_form);
        
      if(!empty($crawler ->selectButton('次へ')->form())){
          #細かいのボタンを2回クリック
          $f_announce = $crawler ->selectButton('次へ')->form();
          $crawler = $client-> click($f_announce);
            
          $s_announce = $crawler->filter('form')->form();
          $crawler = $client->click($s_announce);
        
          return array($client,$crawler);
      }else{
          #次へボタンが出てこない場合ログインエラー
          return;
      }
  }

これでログインをこなし、サイドナビの指示するページまではいけるけどその先がダメ。

認証エラーとなる理由の推測

本当の所は分からないので、あくまで推測です。
ただ、この推測が正しいとなるとGoutteでの情報取得はほぼ無理といって間違いありません。

  • classの値とJavaScriptを組合わせてHTMLからは見えない形でPOSTしているのではないか
  • POSTする値やURLを暗号化している可能性もあり

cookieで行けると思ったのですが、NGという結果。
となると、画面遷移の中で何かが仕掛けられているのだと思います。

ハックまでしてデータ取るなら楽天の用意している方法で取得/処理の方が遥かに省労力。

残る方法は2択

  1. VBSやJSでデスクトップのブラウザ操作をエミュレートし欲しい情報を取得
  2. PHP×ヘッドレスブラウザでエミュレートし欲しい情報を取得

どちらにせよ実ブラウザ操作を組み込まないといけないようです。
その操作をデスクトップから行うかサーバーから行うかですね。

ちなみに、AWSを利用するとIP_BAN食らってもIP変更できるので乗り越えられます。
が、私の様にさくらインターネットとか使ってるとIP変更は出来ないのでBANから立ち直る方法はありません。
ココは安全を考えるとやはりデスクトップからの操作になるのかな。

VBSとかはブラウザ自動操作時にPC占有されてしまうのが最大のネックですけど、1社のデータであれば20分もあれば余裕で採れるからタスクスケジュラーでPC終了含め組んでしまえばOKかなと。

まぁサーバー側で処理させてしまった方が楽なんですけどね。

まとめ

最近は クローラー対策が進んでいてスクレイピングが一筋縄ではいきません。
動的ページのスクレイピングではヘッドレスChromeが一番のツールになる様です。
これならWindows/Macどちらでも使えますし、Linax版もありますしね。

Goutteでも実装できている方、実装方法をご存知な方、いらっしゃいましたら是非教えてください。
よろしくお願いします。

\ 最新情報をチェック /

楽天RMSログイン処理をPHPのGoutteで組んでみたけど意味がなかった” に対して2件のコメントがあります。

  1. hiro より:

    Goutteだけで実装できますよ!
    ちょうど、Laravel Goutteで実装しました!
    imgタグのsrcもリクエストしておくと認証情報が保持されます。
    javascriptで特殊なことはしてないです。
    apiで有料の部分を使わないで、RMSをスクレイピングしたい事情があったので。

    1. akinori より:

      コメントありがとうございます。

      そうなんですね!
      今度チャレンジしてみます!
      と言いましても、こちらにメモ残すこともできない程度に案件が忙しく「いつテストできるか」不明ではありますが...

      良い情報をくださりありがとうございました。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください