Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
JJUG-2018-Fall-MF2
Search
Takeshi Nakamoto
December 15, 2018
Programming
0
540
JJUG-2018-Fall-MF2
Takeshi Nakamoto
December 15, 2018
Tweet
Share
More Decks by Takeshi Nakamoto
See All by Takeshi Nakamoto
APIへのアクセスが急増して慌てた話 / We Should Know our Application Performance
tksh_n6o
0
730
Other Decks in Programming
See All in Programming
A Journey of Contribution and Collaboration in Open Source
ivargrimstad
0
1.2k
C++でシェーダを書く
fadis
6
4.2k
TypeScriptでライブラリとの依存を限定的にする方法
tutinoko
3
750
Jakarta EE meets AI
ivargrimstad
0
340
Macとオーディオ再生 2024/11/02
yusukeito
0
390
TypeScript Graph でコードレビューの心理的障壁を乗り越える
ysk8hori
3
1.3k
카카오페이는 어떻게 수천만 결제를 처리할까? 우아한 결제 분산락 노하우
kakao
PRO
0
120
イマのCSSでできる インタラクション最前線 + CSS最新情報
clockmaker
5
3.2k
ActiveSupport::Notifications supporting instrumentation of Rails apps with OpenTelemetry
ymtdzzz
1
260
AWS Lambdaから始まった Serverlessの「熱」とキャリアパス / It started with AWS Lambda Serverless “fever” and career path
seike460
PRO
1
270
Djangoの開発環境で工夫したこと - pre-commit / DevContainer
hiroki_yod
1
350
Laravel や Symfony で手っ取り早く OpenAPI のドキュメントを作成する
azuki
2
130
Featured
See All Featured
Art, The Web, and Tiny UX
lynnandtonic
297
20k
Embracing the Ebb and Flow
colly
84
4.5k
Faster Mobile Websites
deanohume
305
30k
Measuring & Analyzing Core Web Vitals
bluesmoon
4
140
The Illustrated Children's Guide to Kubernetes
chrisshort
48
48k
Mobile First: as difficult as doing things right
swwweet
222
8.9k
The Cult of Friendly URLs
andyhume
78
6k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Music & Morning Musume
bryan
46
6.2k
Making Projects Easy
brettharned
115
5.9k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
6.9k
4 Signs Your Business is Dying
shpigford
180
21k
Transcript
Selenium WebDriverと ヘッドレスChromeを用いた スクレイピング 2018/12/15 JJUG CCC 2018 Fall 中本
武志 1
自己紹介 中本 武志(なかもとたけし) 株式会社マネーフォワード(2016〜) サービス基盤本部アプリケーション部 サーバーサイドエンジニア(Java) 静岡県駿東郡長泉町在住 2
3 熱海 小田原 新横浜 品川 • 通勤は約1時間 • 終電は品川発22:54 •
週1でリモート勤務 ◦ 保育園の送迎 ◦ 家事 三島
内容 1. ヘッドレスChromeの検討を始めた経緯 2. ヘッドレスChromeの使い方 3. アグリゲーションシステムへの組み込み 4. まとめ 開発中プロジェクトの内容となります。
本番環境での運用を始めていないため、遭遇していない問題がある可能性があります。 4
内容 1. ヘッドレスChromeの検討を始めた経緯 2. ヘッドレスChromeの使い方 3. アグリゲーションシステムへの組み込み 4. まとめ 5
マネーフォワードのアグリゲーションシステム • カスタマイズした HtmlUnit を利用したスクレイピング • OkHttp などを利用したAPI連携 • 様々な金融機関サイトに対応
• 毎分4000セッション https://github.com/HtmlUnit/htmlunit 6
対応金融機関 • 銀行、など ・・・ 2279 サイト • カード ・・・ 141
サイト • 証券、投信、FX・貴金属 ・・・ 87 サイト • ポイント ・・・ 41 サイト • 電子マネー・プリペイド ・・・ 37 サイト • 交通(JAL, ANA) ・・・ 12 サイト • 通販(Amazon, 楽天) ・・・ 10 サイト • 携帯 ・・・ 12 サイト • など ・・・ 計 2678 サイト 7
対応金融機関 • API連携でのアグリゲーションも増えている ◦ 仕様が決まっているので、問題なくデータが取得できる ◦ (基本的には)処理速度も速い ◦ ログインパスワードなども預からない •
とはいえ大多数はスクレイピングを行っている ◦ 最近スクレイピングが難しいサイトが増えてきた 8
スクレイピングの課題 例1) MF KESSAI (https://mfkessai.co.jp/) スクレイピングしようとしたらエラーになった 9
スクレイピングの課題 エラー内容 Caused by: net.sourceforge.htmlunit.corejs.javascript.EcmaError: TypeError: Cannot find function resolvedOptions
in object [object DateTimeFormat]. https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/resolvedOptions 2012年ごろ策定されたAPI (?) 10
スクレイピングの課題 エラー内容 Caused by: net.sourceforge.htmlunit.corejs.javascript.EcmaError: TypeError: Cannot find function resolvedOptions
in object [object DateTimeFormat]. https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/resolvedOptions 2012年ごろ策定されたAPI (?) 11 エラーになる箇所と同等の処理を実装して回避
スクレイピングの課題 例2) HtmlUnitの改修 とあるサイトのリニューアル後にスクレイピングできなくなった com.gargoylesoftware.htmlunit.ScriptException: ReferenceError: Assignment to undefined "getHoge"
in strict mode var getHoge = function getHoge() { alert ('foo') } 名前付き関数式でパースに 失敗するパターンが存在した 12
スクレイピングの課題 例) HtmlUnitの改修 暫定対応後に、根本対応を行い、HtmlUnit に報告 13
スクレイピングの課題 • HtmlUnit ではスクレイピングが難しいサイトが増えた • リニューアル等でこれまでできていたスクレイピングが できなくなることが増えた ◦ 解決策を模索するコストが増加 GUIなし(ヘッドレス)で動く本物のブラウザを使ったスクレイピング
を 選択できるようにしておく 14
ブラウザのヘッドレスモード • 2018年7月当時、ヘッドレスモードがあったのは ◦ Google Chrome v68 ◦ Mozilla Firefox
v61 • とりあえず Chrome を使うことにした ◦ ブラウザシェアの多い方に 15
内容 1. ヘッドレスChromeの検討を始めた経緯 2. ヘッドレスChromeの使い方 3. アグリゲーションシステムへの組み込み 4. まとめ 16
ヘッドレスChromeとは Google Chrome v59 から利用できるようになった GUIなしでブラウザを動作させる機能 https://developers.google.com/web/updates/2017/05/nic59 より 17
制御方法 • Chromeをプログラムから操作する手段はいくつか存在する ◦ puppeteer(パペティア) とかが有名 • Java アプリケーションから利用できるものは2つくらい ◦
Chrome DevTools Protocol(CDP) ◦ Selenium/WebDriver 18
制御方法 構成 App App chromedriver WebSocket / CDP HTTP/JSON WebSocket
/ CDP 19 Selenium
Chrome DevTools Protocol Chrome DevTools Protocol(CDP) を使って操作することができる • WebSocket で通信
• JSON 形式のコマンド 20 https://chromedevtools.github.io/devtools-protocol/
Chrome DevTools Protocol { "method": "Page.navigate", "params": { "url": "https://moneyforward.com/"
} } ページ遷移コマンド DevTools Protocol エンドポイントに対して、コマンドを渡して操作する 21
Chrome DevTools Protocol DevTools Protocol のみだとけっこう煩雑 22 - 要素を検索 (DOM.performSearch)
- 検索結果を取得 (DOM.getSearchResults) - 検索結果のボックス情報を取得 (DOM.getBoxModel) - ボックス情報から要素の中心座標を計算 - 中心座標で mousePressed イベントを発火(Input.dispatchMouseEvent) - 中心座標で mouseReleased イベントを発火(Input.dispatchMouseEvent) (注: デバッガ経由での観察結果で、実装の一例です。) ある要素をクリックするために必要な処理
Selenium WebDriver ブラウザ操作の自動化ツール • Chrome も含めた、ブラウザ共通の操作用API • 様々な言語での実装がある 23
Selenium WebDriver App chromedriver ブラウザ固有の WebDriver実装 geckodriver edgedriver etc ...
WebDriver クライアント JSON Wire Protocol (HTTP) 24
chromedriver chrome/chromium 向けの WebDriver 実装 WebDriver 標準API以外にも、いろんなAPIが定義されている https://chromium.googlesource.com/chromium/src/+/master/chrome/test/chromedriver • W3C
standard endpoints • Json wire protocol endpoints • Extension commands from other specs • ChromeDriver specific extension commands • Commands of unknown origins CDPコマンドを渡すAPIもある 25
chromedriver 指定可能なオプションやAPIの使い方などは テストコードを見てみるとわかりやすい https://chromium.googlesource.com/chromium/src/+/master/chrome/test/chromedriver/test/run_py_tests.py 26
chromedriver findElement というコマンドは最終的にJavaScript として実行されていた https://chromium.googlesource.com/chromium/+/trunk/third_party/webdriver/atoms.cc 27
CDP / WebDriver の比較 機能(Chromeの場合) CDP WebDriver 多機能 (DevTools でできることができる)
主にブラウザ操作関連 WebDriver でできることはCDPでもできる 28
CDP / WebDriver の比較 実装(Chromeの場合) CDP WebDriver - ほぼ自前で実装する必要がある (ライブラリはあったが、ライセンスの関係で
見送った) - 学習コストが高そう (puppetterなどのライブラリの実装を読んで 学んだ) - Selenium が提供するクラスが利用可能 - ドキュメントが豊富 - 事例も豊富 29
スクレイピングの要件 アグリゲーションシステムに組み込むための最小限の要件 1. プロキシの利用 2. Cookie の利用 3. ファイルダウンロードの利用 2.
と 3. については問題なく行えた。 4. も動作サンプルは実装できた。 30
ファイルダウンロード HtmlUnit 31 • 同一プロセス内で動作しているため、アプリケーションから直接アクセス可能 ◦ ダウンロード完了イベントなどもわかる ヘッドレスChrome • 別プロセスのため、ファイルシステムを介して取得する必要がある
◦ ダウンロード完了イベントも明示的に取得しないといけない
ファイルダウンロード CDP ダウンロードディレクトリの指定 Page.setDownloadBehavior コマンドで可能 ダウンロード完了判定 ディレクトリのファイル名判定(xxx.crdownload) または リクエスト完了イベントハンドリング(Network.loadingFinished) など
32
ファイルダウンロード WebDriver ダウンロードディレクトリの指定 chrome 起動時のオプションとして設定可能 (prefs.download.default_directory) ダウンロード完了判定 ディレクトリのファイル名判定(xxx.crdownload) または リクエスト完了イベントハンドリング(Network.loadingFinished)
Performance Log を有効にするとCDPと同様のイベントログを取得できる 33
どちらを使うか • CDPのほうがいろいろできるが、実装コストが高い • WebDriver は機能としてはCDPに劣るが、ライブラリの整備な どを考えると使いやすい 実験的な位置づけで、速くリリースに持っていけるWebDriverを採用 34
内容 1. ヘッドレスChromeの検討を始めた経緯 2. ヘッドレスChromeの使い方 3. アグリゲーションシステムへの組み込み 4. まとめ 35
スクレイピング実装 HtmlUnit API WebDriver WebDriver を利用するサービスは、Chrome 及び chromedriver がインストール された特定のサーバーに振り分ける実装を追加
36
構成 アグリゲーション chromedriver 外部サービス systemd 外部サービス 外部サービス server 37
構成 • chromedriver は daemon として起動しておく ◦ スクレイピングセッション毎にchromedriverとchromeが起 動するのは重そうだったので(感想) ◦
同時スクレイピング数を絞った状態でリリースして調整す る予定 38
追加開発した機能 • Selenium 提供の機能でほぼ対応できた • chrome が起動しっぱなしにならないよう確実に閉じるようにし た • 既存の開発スタイルに合わせるため、明示的な待機の実装を
ラップ ◦ 指定時間を過ぎても例外を投げないで戻す ◦ エラー画面になったことを検出できるようにした 39
使ってみた感想1 • スクレイピングできなかったサイトができるようになって 単純にうれしい ◦ スクレイピングできないサイトがなくなった感がある • HtmlUnit と比べてそこまで遅くなった感じはない ◦
ページ遷移時などは速く感じることも ◦ 外部サイトとの通信にかかる時間のほうが大きい ◦ 単純な動作速度よりも、正しいデータを取得できるようになるこ とのほうが重要なため問題ない 40
使ってみた感想2 • けっこうリソースを消費する(CPU/メモリ) ◦ 同時接続数を増やした場合の負荷がどうなるか ◦ 計測した値を元に調整していく • chrome のバージョンアップなどへの追従はどうするか
◦ apt では基本的に最新バージョンしかインストールできない ◦ リポジトリをコピーしてくるなどが必要そう • 既存のライブラリ資産を使えるようにしたい ◦ HtmlUnit 提供のクラスのラッパーなど ◦ 便利メソッドを使えるように改修しないといけない 41
内容 1. ヘッドレスChromeの検討を始めた経緯 2. ヘッドレスChromeの使い方 3. アグリゲーションシステムへの組み込み 4. まとめ 42
まとめ • HtmlUnit 以外のスクレイピングの選択肢を準備したい ◦ そのためにヘッドレス chrome を使う • Chrome
DevTools Protocol は使えたら使いたい ◦ ライブラリ整備ができれば • WebDriver 便利 ◦ サクッと使い始められる ◦ chrome のバージョンアップ等の運用に課題 ◦ リソースは結構消費する模様 • 定量的な評価は今後の課題 43
Thank you! 44
Javaエンジニア募集中 • 扱うデータへ強い責任感をお持ちの方 • この世界に流れるデータを綺麗にしたい!というパッションをお持ちの方 • 大規模トラフィックを捌いてみたい方 • ミドルウェアを使い倒したい方 45