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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Go

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

Webサイト

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

AngularJS

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

Q&A

解決済

2回答

5239閲覧

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

退会済みユーザー

退会済みユーザー

総合スコア0

Go

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

Webサイト

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

AngularJS

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

1グッド

3クリップ

投稿2017/11/11 17:46

編集2017/11/11 17:49

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

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

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

普通に

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

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

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

toshikiohnogi👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

あー…これは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 04:14

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/11/12 04:26

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

2017/11/12 04: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 04:45 編集

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

2017/11/12 05:13

うーん、私としてはagoutiはコードを中継しているだけで大した事はしてないし、 Golangの挙動が環境によってコロコロ変わる事は考えにくいですね。 例えばHerokuのマシンスペックがローカルマシンと比べてヘボすぎて、 AngularJSで吐き出される予定のサブミットボタンがまだレンダリングされてない可能性が考えられます。 もしagoutiにwait系の機能が使えるなら試してみてください。 トライ&エラーがHerokuでは辛そうなので、ConoHaの一番しょぼいVPSインスタンスを借りてそこで試行錯誤するのも良いかもしれません。
退会済みユーザー

退会済みユーザー

2017/11/12 06:23 編集

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

0

不可能ではありません.

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

投稿2017/11/11 22:36

Yatima

総合スコア1159

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/11/12 04:27

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問