質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

Goutte+ヘッドレスブラウザ : クリックの仕方がわかりません

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,133

cocoyashi

score 15

前提・実現したいこと

ヘッドレスブラウザ(Chrome)を起動して、PHP(Goutte)で指定URL先のWebサイトから情報をスクレイピングするコードを書いています。管理者権限のあるサーバに、ヘッドレスブラウザやWebsocketやらをインストールの上、ターミナルで「$php ○○○.php」して実行しています。

ページ半ばにある「イベントスケジュール / チケット」の下にある日付(例:06/07(金)など)をクリックすると、cssのclassが動的に変更され、チケット情報が変更されます。ヘッドレスブラウザ+Goutteでクリックして、変更されたチケット情報を取得したいのですが、当方、プログラム初心者のため、どうすれば良いのかわかりません・・・。

該当ページ

https://mysterycircus.jp/events

発生している問題・エラーメッセージ

PHP Fatal error:  Uncaught TypeError: Argument 1 passed to Symfony\Component\BrowserKit\Client::click() must be an instance of Symfony\Component\DomCrawler\Link, instance of Symfony\Component\DomCrawler\Crawler given, called in /home/scraping/site/test_f2.php on line 98 and defined in /home/scraping/vendor/symfony/browser-kit/Client.php:286
Stack trace:
#0 /home/scraping/site/test.php(98): Symfony\Component\BrowserKit\Client->click(Object(Symfony\Component\DomCrawler\Crawler))
#1 {main}
  thrown in /home/scraping/vendor/symfony/browser-kit/Client.php on line 286

該当のソースコード

<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../dao/dao.php';
use WebSocket\Client;
use Symfony\Component\DomCrawler\Crawler;

/* 初期設定 */
$goutte = new Goutte\Client();
$crawler = new Crawler(null);

$domain = "https://mysterycircus.jp";  //URL
$pathName = "/events"; //カレンダーURL
$parent_calendat_id = 20; //DB calender id

$pathContents = '._scheduler_container'; //イベントリストのクラス
$pathPagerWrap = '._calendar_daysSet';
$pathPager = '._calendar_days_box_a';
$pathEventWrap = '._scheduler_main'; //イベントの囲み
$pathEvent = '._scheduler_event_wrapper'; //イベント
$pathTitle = '._scheduler_event_title'; //イベントタイトルまでのパス
$pathImg = '._scheduler_event_pic img'; //イベント画像までのパス
$pathDetail = '._scheduler_event_pic a'; //詳細ページまでのパス
$pathText = ''; //イベント紹介文までのパス
$pathDate = '._scheduler_event_description'; //イベント日付までのパス


/* URLを作成する */
$urls[] = $domain . $pathName;

//Chrome起動
$cmd = 'google-chrome --disable-gpu --headless --remote-debugging-port=9222';
exec($cmd . " > /dev/null &");

//Chromeの接続URLを取得
do {
    $endpoints = json_decode(`curl -s http://localhost:9222/json`);
} while (empty($endpoints));
$endpoint = $endpoints[0]->webSocketDebuggerUrl;

//接続クライアント作成
$client = new Client($endpoint);

//Pageドメインのイベント受信を有効化
$client->send(json_encode([
    'id' => 1,
    "method" => 'Page.enable'
]));

//ページを開く
$client->send(json_encode([
    'id' => 2,
    "method" => 'Page.navigate',
    "params" => ['url' => $urls[0]]
]));

//フレームIDが取得できるまで待機
while ($data = json_decode($client->receive())) {
    if($data->id == 2){
        $frameId = $data->result->frameId;
        break;
    }
}

//画面の読み込が終わるまで待機
while ($data = json_decode($client->receive())) {
    if (@$data->method == 'Page.frameStoppedLoading' && @$data->params->frameId == $frameId) {
        break;
    }
}

//HTMLのDocument情報を取得
$client->send(json_encode([
    'id' => 3,
    'method' => 'DOM.getDocument',
    'params' => []
]));
while ($data = json_decode($client->receive())) {
    if($data->id == 3){
        $nodeId = $data->result->root->nodeId;
        $backendNodeId = $data->result->root->backendNodeId;
        break;
    }
}

//HTMLソースを取得してスクレイピングする
$client->send(json_encode([
    'id' => 4,
    'method' => 'DOM.getOuterHTML',
    'params' => ['nodeId' => $nodeId]
]));
while ($data = json_decode($client->receive())) {
    if($data->id == 4){
        $crawler->addHtmlContent($data->result->outerHTML); /* DOM取得 */
        $crawler = $crawler->filter($pathContents); /* DOM修正 */
        $num = $crawler->filter($pathEvent)->count(); /*イベント数*/

        //■■■■■■■ここに「イベントスケジュール / チケット」の下にある日付をクリックする文を追加■■■■■■■
        $next = $crawler->filter($pathPagerWrap)->filter($pathPager)->eq(1);
        $crawler = $goutte->click($next);
        //■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
        break;
    }
}

exec('pkill -f "' . $cmd . '"');

試したこと

1)$goutte->click($crawler->selectLink('06/07(金)')->link());
2)$goutte->click($crawler->selectLink('._calendar_days_box_a')->eq(1)->link());
3)$link = $crawler->selectLink('06/07(金)')->link();
  $crawler = $goutte->click($link);
4)$next = $crawler->filter($pathPagerWrap)->filter($pathPager)->eq(1);
 $crawler = $goutte->click($next);


などと、検索しては試し、検索しては試しを繰り返してるのですが、
2日経ってもやり方がわかりません・・・。助けて頂けると嬉しいです・・・。

イメージ説明

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    退会済みユーザー

    2019/06/06 12:51

    ソースは```や`で囲ってください。
    前者は複数行のコード。後者は単行のコードに基本的に使います。

    キャンセル

  • cocoyashi

    2019/06/06 13:44

    初めての投稿だったので、間違えていました。
    指摘ありがとうございます^^

    キャンセル

回答 2

checkベストアンサー

0

ちょっと回りくどいやり方をしていますね。
裏でヘッドレスChromeを起動してremote debuggingしてると。
Goutteを使っている以上、ヘッドレスChromeを通しても動的なページはスクレイピングできないのではないでしょうか。
直接PHPからヘッドレスChromeを使った方が単純で分かりやすいと思いますよ。
環境構築で参考になるURLを紹介しておきます。

PHPでChromeを操作(クロール)
https://note.mu/743/n/n7367632b1e19

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/11 10:06

    Goutteを使っている以上は、動的ページをスクレイピングできないんですね・・・。
    ずっと頑張っていました笑

    URLありがとうございます!拝見いたします

    キャンセル

0

Goutte PHP Pythonと色々試した結果、Js Puppeteerに落ち着きました
ありがとうございました 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る