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

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

ただいまの
回答率

90.99%

  • Webサイト

    933questions

    一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

  • AngularJS

    530questions

    AngularJSはオープンソースのJavaScriptフレームワークです。ブラウザ上で動作するウェブアプリケーションの開発にMVCアーキテクチャを取り入れることを目的としています。

  • Go

    422questions

    Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

AngularJSを採用しているサイトをウェブスクレイピングする方法はありますか?

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 705

DDxlk

score 109

タイトルの通り、AngularJSを採用しているサイトをウェブスクレイピングしたいです。

環境は
Golang
"github.com/PuerkitoBio/goquery"
を使います。
(Goやgoqueryでなくても構わないのですが。)

サイトに対してGETリクエストをし、返ってきたレスポンスボディ(HTML)を使ってスクレイピングしたいです

普通に

doc, _ := goquery.NewDocumentFromResponse(レスポンス)


とすると、AngularJSで生成される要素が取れません

AngularJSを採用しているサイトに対するウェブスクレイピングは不可能なんでしょうか

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+4

あー…これはHTMLとは何なのか、普段使っているWebブラウザ(IEやChrome等)が何をやってるか知らなきゃ解決出来ませんわ

超ざっくりと流れを説明すると、
HTMLというのはSGML系に属するテキストファイル
オンラインでドキュメントを管理する為に、見出しは<h1>xxx</h1>のxxxの部分に書いてくださいねというルール決めを行って作られたのがHTML。

ここ重要、HTMLはただのテキストファイル

Chrome等のブラウザは、Webサーバにアクセスして、このHTMLというテキストファイルをダウンロードしてくる。
このHTMLを隅々まで解析して、「CSSが格納されているから表示用にレイアウトを配置しなおすわ」「JavaScriptが格納されているから、HTMLの構造を追加変更削除するわ」といった修正を加えて画面の表示結果に反映している。


これがGolangのライブラリとどう関係するねん?

AngularJSを採用しているサイトをウェブスクレイピングがしたい

"github.com/PuerkitoBio/goquery"というライブラリの使い方の話に戻るよ。
スクレイピング対象のURLへアクセスすると、HTML(単なるテキストファイル)が払い出される。
その単なるテキストファイルをライブラリを使って解析して、構造体や文字列として抽出。

でもCSSやJavaScriptはブラウザが便利だから画面表示するユーザーの事を考えて、
勝手に動作している追加機能なんだよ。
HTML自体の文書構造としては関係無いからHTMLの役目からは切り離されてるんだよ。

えっ、JavaScriptでHTMLの文書構造が変更されたら?
"github.com/PuerkitoBio/goquery"でどうやって抽出するの?

できる訳無いでしょ!JavaScriptまで解析し始めたらChromeの全てをまるっと取り込んだ数百MBの超大作になるよ!!
だから単なるテキストファイルを解析するライブラリ以上の事は出来ない。
AngularJSにかぎらず、JavaScriptでHTMLの構造を組み替えるページ全て全滅というわけ。

これがスクレイピングの2大弱点の一つなんだよ。
まずその会社が公開しているWebAPIやRSSで代用できないか、
公開してないなら諦める事を視野にいれろと言われるのはこのためだね。


どうしてもJavaScriptで書き換わるページをスクレイピングしたい

可能
Golangとは関係ない話になるけどね。

そもそもブラウザしかHTMLとJavaScriptを連動して動かせない以上、
マクロか何かで、本物のブラウザを操って無理やり動かすやり方が必要になるわけだね。

Chromeはwebkitという有名レンダリングエンジンを搭載していて、
webkit自体はオープンソースで誰でも入手可能。
スクレイピング目的だから画面表示要らないよね、このwebkitにマクロを読み込ませて外から操って結果を抜き出すというPhantomJS(2011~)というブラウザが登場した。

ただこのPhantomJS、依存パッケージのインストールが面倒だったり、日本語が豆腐に文字化けしたりとすこぶる使い勝手が悪かった。
ももそのままChromeやFireFox使いたいよ!!
その願いがそれらのブラウザの製作者に通じて、ChromeやFireFoxではスクリプトで動かすヘッドレスモードが実装されたのだ。
これが最近の話。

ここで悲報、Golangにはこのヘッドレスブラウザを操るライブラリがない。
見当たらなかっただけで、探せば見つかるかもしれないし、技術力と情熱さえあれば自作出来るレベルだろうけどね。
この辺のジャンルはNode.jsが強くて、他の言語は遅れてるってのが現状だね。

というわけで、JavaScriptのコードでヘッドレスブラウザを動作させて結果を標準出力に吐き出して、
Golangからシステムコマンドnode hogehoge.jsを実行して、結果を標準出力越しに受け取り、処理を継続する流れになる。


それ"github.com/PuerkitoBio/goquery"を使う意味ある?

もうないね、ヘッドレスブラウザがJavaScript(Node.js)のコードしか受け付けない以上、
全部Node.jsでやってしまえばいいわけだし…

ただまぁ、AngularJSで作用後のHTMLのbodyタグ直下を全て受け取って、
まるっとgoqueryの変換機に投げ込んでやればgoqueryで継続して使えそうではあるね。

予めハマリポイントを推測しておくならば、
ブラウザがHTMLを受け取ってからどのくらいの時間を掛けて、AngularJSを解析してHTMLの文章を書き換えるのか分からないよね。
だから、ヘッドレスブラウザに搭載されている「○○を待つ」という機能を活用することになる。

私はPhantomJSしか触ってないけど、適当に10秒間待つ事もできるし、
<div class"hoge">xxx</div>が生成されるまで待つという具体的で確実な手法も存在する。


めんどくさい、他の方法ないの?

AngularJSで決まりきった情報に書き換えるようなページはそうない。
大抵「Ajax通信を飛ばして、追加情報をJSON形式で、それを解析してHTMLを書き換えている」

後はもう分かるね?
Chromeならデベロッパーツール(F12)のネットタブを開いて、Ajax通信の接続先を覚えておけばいい。

後はGolangでHTTP通信でJSONを直接とりに行ってパースすれば解決。
スクレイピングなんて要らなかったんや。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/12 13:26

    個性ある回答ありがとうございますw!
    一応、github.com/sclevine/agouti という、goで使えるウェブドライバーのクライアントがあるので、これを使えば確かにできました。ただこれは不安定(自分の環境では動くけど、herokuに乗せるとなぜかうまくいかなかったり)なので、悩んでました。

    キャンセル

  • 2017/11/12 13:37

    agoutiは下記のコードでページを宣言するようですね。
    testPage("ChromeDriver", chromeDriver.NewPage)
    https://github.com/sclevine/agouti/blob/master/internal/integration/integration_test.go

    herokuに関して詳細は知りませんが、
    コンテナという軽量Linuxの仮想マシン内で動作する為、依存パッケージ不足で死んでるケースが考えられますね。
    PhantomJSくらいなら入れられるかと思うので、下記のページを元に導入してみては?
    http://logic.moo.jp/data/archives/1061.html

    まぁ、AngularJSを使っているようなシングルページアプリケーションは、
    大抵がAjaxで追加コンテンツを動的にダウンロードしている設計ですので、
    Ajaxの部分をエミュレートして捕まえるのが一番楽ではあります。

    キャンセル

  • 2017/11/12 13:45 編集

    わざわざ調べていただいて恐縮です。
    herokuの不具合というのは
    例えば
    page.FindByClass("submit")..Submit() //submitクラスの要素を探してサブミットする
    このコードが、ローカルだと動くのに、herokuで動かすと「submitクラスは存在しません」と言われると言ったバグです。
    依存関係は大丈夫だと思います。
    その前までのFind系関数ではエラーが出てないのに途中でこのようなエラーが出ているので、動いてはいるんだと思います。
    agoutiではPhantomJSも使えますし、クロームのヘッドレスモードも使えます

    キャンセル

  • 2017/11/12 14:13

    うーん、私としてはagoutiはコードを中継しているだけで大した事はしてないし、
    Golangの挙動が環境によってコロコロ変わる事は考えにくいですね。

    例えばHerokuのマシンスペックがローカルマシンと比べてヘボすぎて、
    AngularJSで吐き出される予定のサブミットボタンがまだレンダリングされてない可能性が考えられます。
    もしagoutiにwait系の機能が使えるなら試してみてください。

    トライ&エラーがHerokuでは辛そうなので、ConoHaの一番しょぼいVPSインスタンスを借りてそこで試行錯誤するのも良いかもしれません。

    キャンセル

  • 2017/11/12 15:23 編集

    すみません
    回答の一番最後を見逃していました!
    実はコメントする前に、私自身も通信先を見つけまして、jsonを受け取れることがわかって「スクレイピングなんて要らなかったんや。」という結論に達していましたw
    ですが、あまりに丁寧な回答だったため、「自己解決しました」とは言いづらく、webdriverに関してわからないことも多かったので、無駄な問答をしてしまいました。
    申し訳ありませんでした
    また、丁寧で詳しい回答ありがとうございました!

    キャンセル

+1

不可能ではありません.

ご存知とは思いますが,AngularJSなどのJavaScriptフレームワークは手元で実行される必要があります.
そのため,ブラウザやそれに相当する機能を持つツールが必要となります.
Headless Chromeなどが該当します.
ヘッドレス Chrome ことはじめ

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/12 13:27

    回答ありがとうございます!
    当方ウェブドライバーはすでに試しており、ウェブスクレイピングでどうにかならないかなぁと思っていました。

    キャンセル

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

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

関連した質問

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

  • Webサイト

    933questions

    一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

  • AngularJS

    530questions

    AngularJSはオープンソースのJavaScriptフレームワークです。ブラウザ上で動作するウェブアプリケーションの開発にMVCアーキテクチャを取り入れることを目的としています。

  • Go

    422questions

    Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。