基本的にAlteryxでWEBスクレイピングを行う時は、ログインなどが必要のないサイトに対してダウンロードツールでアクセスし、取得したURLのHTMLファイルを加工する、というのが通常のやり方です。今回はログインが必要なサイトに対してログインを行い、情報を取得する方法をご紹介します。
バックグラウンドストーリー
私はWordPressで主にAlteryx関係のブログを書いていますが、記事が増えてくると自分のブログについてのダッシュボードが作りたくなりました。半分くらいは自己満足で、見てニヤニヤしているだけかもしれませんが、場合によっては有用なことがあります(少なくともどんなTipsがあるのかを発見しやすくなります)。
WordPressからまとまった情報を得るには、いくつかの方法があります。まずはどのようなダッシュボードができそうか、データを見ながら考えることにしました。この場合一番手っ取り早いのは、WordPressがデフォルトで提供しているエクスポート機能です。これは、コンテンツをXML形式でダウンロードできるため、このデータを用いてダッシュボードを作ることにしました。XMLをパースするのは若干面倒ではありますが、コツを掴めばそれほど難しいわけでもありません。まず、この方法で一旦ダッシュボードができあがりました。
ただ、WordPressのエクスポート機能を使うには、いったんサイトにログインする必要があるため、自動化向きではありません。そのため、エクスポート機能以外の方法を探しました。WEBサイトから情報を得る一番定番となる方法はRestAPIを使ってデータを入手することです。WordPressは幸いなことにAPIを提供していたので、これを使って実装してみました。
一旦はこれで解決、となりましたが・・・自分の所属会社でも同様にWordPressでブログを書いています。同じダッシュボードがそのまま会社のブログでも使えればいいなぁ、と思い、さっそく会社のWordPressでも同じような構成を取ろうとしました。ところが、私の会社のWordPressはAPIの機能を無効にしています(まぁ、セキュリティを考慮して自分で無効にしたのですが・・・まさかこんなところで引っかかるとは思いもよりませんでした)。
しかし、だからといって毎回手動でXMLファイルをダウンロードしたくはありません。
そこで改めて考えたのが今回の方法で、Alteryxでログイン処理ができないか、です。
どうやって行うのか?
基本的にはダウンロードツールを使います。Alteryxのダウンロードツールは、curlとほぼ同じことを行うことが可能です。PythonならばrequestsなどのHTTPプロトコルでアクセスするライブラリとやってることはそれほど遜色はありません。ですので、基本的にはcurlで自動化をする手法を参考にしていますが、残念ながらcurlほど親切ではないのでAlteryxではどうしても作り込まないといけない部分があります。
curlとは?
ところで、curlとはどのようなものなのでしょうか?Wikipediaによると以下のようなものと説明されています。
curlはURLシンタックスを用いてファイルを送信または受信するコマンドラインツールである。
通常、ある特定のWEBサイトを閲覧する際、ブラウザを通じて人間がURLを入力してボタンを押したりするわけですが、この際にブラウザが特定のURLに対してHeader情報とともにPayloadをPOSTしたりGETしたりしています。Alteryxのダウンロードツールやcurlも同様に特定のURLに対してHeader情報を付加し、PayloadをPOSTなどすることが可能です。つまり、WEBブラウザとWEBサイトで行われているやり取りをWEBブラウザの代わりにAlteryx/curlで行うことになります。
諸注意
この方法についていくつか注意点があります。
CAPTCHAの突破はできない
ロボット避け認証であるCAPTCHAが使ってある場合は対応は非常に困難です。もしDeep Learningが得意で画像などを自動的に判断できればできるかもしれませんが、おそらく対策されていると想定されます。
サイトによって実装が異なるのであるサイトでできた方法が他のサイトでそのまま使えるわけではない
WEBサイトによって認証方法や画面の作り方は大きく異なります。今回やったような調査方法は汎用的に使えますが、実際の実装は汎用的ではなく、個別のサイトに対してオーダーメイドで対応する必要があります。特にGMailのように動的に画面を書き換えるようなサイトの解析は非常に難しいです。
サイトに負荷をかけないようにしましょう
アクセスするサーバーへの負荷がかからないよう、大量のデータのダウンロードやアクセスは控えるようにしましょう。
サイトの規約に抵触しないことを確認しましょう
明示的にスクレイピングや自動化を禁じているサイトはルールを守りましょう。
実際の方法
まず、Alteryx以外で最低限理解が必要になるブラウザのDeveloperツールについて説明したいと思います。
Developerツールについて
Google ChromeのDeveloperツールはご存知でしょうか?もしくはFirefox、Edgeでも構いませんが実は各ブラウザには同等のツールが搭載されています。
この中の「ネットワーク」タブを使うのが今回のポイントです。
ネットワークタブでは、WEBブラウザとサーバーのやり取りを見ることができます。SaaSアプリのデバッグにも使われたりします。このログを保存することも可能で、エクスポート機能を使えば、HARファイルとして保存することが可能です。なお、デフォルト設定だと画面遷移時にログがすべて消えてしまうので、「ログを保持」にチェックを入れてください。
ざっくりと、画面構成は以下のようになります。
基本的には、Developerツールを表示した状態で情報を得たいサイトのログイン画面からアクセスを開始していきます。また、このとき通常のブラウザタブではなく、シークレットタブを使うようにしてください(過去のアクセス情報があるとその情報はある前提となってしまい、解析がうまくいきません)。
Developerツールを使って調べること
Developerツールを使い、ログインしてから欲しい情報を取得するまでのブラウザとサーバーの一連のやり取りを調べていく必要があります。つまり、ざっくりとブラウザとWEBサイト間のログインのやり取りは以下のように行われています。
この情報を用いて、Alteryxでどのような処理をさせるのかを決めていきます。ログはHARファイルで保存はできますが、リクエストで戻ってきたときの内容は後からDeveloperツールで確認できなくなってしまうため、Alteryxの実装時は再度同じことを行う必要があります。つまり、初回のDeveloperツールによるログ取りは、どのような情報を送り、どのような情報を受け取って、再びどの情報を使ってアクセスを行っていくか、というのをざっくり抑えるためのものです。2回目のアクセスでDeveloperツールを見ながらAlteryxに実装を行っていく、ということになります。もちろん2回目のアクセス前に一度ブラウザのシークレットウィンドウを閉じてログインからやり直す必要があります。
この一連の処理の中で、一番のポイントは②で取得されるログイン画面の情報です。受信したHTMLの情報を元にログイン用WEBフォームから送信するデータをAlteryxでうまく組み立てられるかどうかがポイントです。それ以外はほぼテンプレート的にできると思います。
実際にアクセスしてみる
今回はGitHubをテーマとして扱いたいと思います。GitHubは様々なセキュリティオプションがありますが、一度でもログインしたことのあるPCで、セキュリティはデフォルト設定(二段階認証などをつかわない)である前提とします。
ログイン
まず一番の難問はログインすることです。最初に、ログインするときのURLを指定してアクセスします。GitHubのログインURLは「https://github.com/login」です。
必ず新規に立ち上げたブラウザのシークレットタブで、Developerツールを起動した状態でログイン用URLを入力します。これにより、ログイン用のURLから画面を表示するための一連のデータをすべてブラウザが自動的にダウンロードします。もし、シークレットタブでも一度ログインしてしまうと、その時のCookieを保持してしまうため、必ずブラウザの立ち上げ直した状態で調査を進めましょう。
ログイン用のURLはログの必ず先頭にあるので、まずはこれを確認しましょう。
ここで確認するのはヘッダー情報です。リクエストヘッダーがブラウザ側からアクセスする際のヘッダーです。レスポンスヘッダーはサーバー側から帰ってきたデータになります。ですので、リクエストしたものがレスポンスで取得できる、ということになります。また、最初はリクエストメソッドはGETになります。基本的にはヘッダー情報のみでボディ(Payload)には何もセットしないためです。
ここで、レスポンスヘッダーをまず見ます。ここにSet-Cookieというものがあります。ブラウザはこのCookieをセットして次のアクセスを行う必要があります。このCookieをメモっておきましょう。ここで見ているように複数のSet-Cookieがある場合もあります。
さらに、レスポンスも見ておきましょう。これが実際に取得しているログインページの内容となります。この内容は、左側のブラウザ画面で画面遷移すると見れなくなるのでご注意ください。可能であればレスポンスをHTMLファイルとして保存しておきましょう(あとで隠し項目などをここから拾う必要があります)。Chromeの場合はレスポンス画面で右クリックから保存することが可能です。
次に、実際にログインしてみましょう。左側の画面の方にユーザー名とパスワードをセットしてSign inボタンを押してください。
ID/Passが間違っていなければ無事にログインできると思いますが、Developerツールを見ると、loginの次のドキュメントのURLは「https://github.com/session」です(これはフィルタでドキュメントのみにすれば見つけやすいと思います)。その後何もしないのにgithub.comというドキュメントに最終的に移行しています。これはsessionのステータスコードが302となっている通り、リダイレクトがかかっているため自動的にgithub.comに移行している、ということです。
ここ(sessionというURL)ではリクエストメソッドがPOSTになっています。つまりブラウザのログイン画面で操作すると、「https://github.com/session」に対してPOSTしている、ということになります。このとき、リクエストヘッダーのCookieを見てみましょう。
これと、ログイン画面のレスポンスヘッダーにあったSet-Cookieを比べます。Set-Cookieのうち、POSTしたときのCookieで使用しているもののみSet-Cookieから取得しヘッダーにCookieとして付加する必要がある、ということです。その他のヘッダーの内容も場合によっては必要になるので一応メモしておいてください。
さらにペイロードを確認します。ペイロードはブラウザがフォーム情報としてサーバー側に送信している情報で、上のCookieとともにPayloadにセットしてPOSTする必要があります。
この「ペイロード」の情報をPayloadとしてリクエストの本体部分にセットする必要があります。ここで、loginとpasswordはもちろんご存知のものを使いますが、commitという項目などは固定の項目となります。それ以外に、authenticity_token、timestamp、timestamp_secretは動的に生成された項目です。さて、この動的に生成されている項目はどこにあるのでしょうか?答えは、loginしたときのURLのレスポンス(loginのレスポンス)にあります。この中を検索すると、無事に見つかるはずです。実際に探してみましょう。
メモ帳などで保存していたテキストに検索をかけると無事に見つかります。これら(authenticity_token、timestamp、timestamp_secret)の項目はHidden属性としてフォームに埋め込まれています。
これらもメモしておきましょう。なお、これらの項目はWEBサイトごとに全く異なるのでご注意ください。
これでログインの準備はできました。さてDesignerに戻りたいと思います。
Designerでログインする
Designerでは以下のような形になります。
- https://github.com/login にアクセスしてログイン画面とCookieを取得(①と②)
- ログイン画面の情報とログイン情報からログイン用Payload情報を作成
- https://github.com/session にアクセスしてCookieとPayloadを使ってログイン(③と④)
- 最終的なCookieを作成
これをブラウザのフローと同じように書くと以下のようになります。言葉はなるべくAlteryxのDownloadツールの用語に置き換えています。
丸数字と箇条書きリストの数字は一致していないのでご注意ください。リストの1が①②に該当し、リストの3が③④に該当します。
1と2の部分は以下のようなワークフローとなります。
3と4の部分は以下のようなワークフローとなります。
ログインURLへアクセス(①)
最初に、https://github.com/login にアクセスします。この時のダウンロードツールの設定は、ヘッダーにuser-agentをセットし、ペイロードのHTTPアクションを「GET」にするだけです。
user-agentは適当にテキスト入力ツールに入れておきましょう(Designerはなぜかuser-agentをデフォルトで送信してくれないので、自分でセットする必要があります。これはAPIでも同様にしないとひっかかるケースがあるのでご注意ください)。
②の部分はダウンロードツールの結果です。これで、以下のようにDownloadHeadersに「HTTP/1.1 200 OK」と帰ってくれば成功です(サイトによっては302のケースもあります)。いずれにしても、ヘッダにSet-Cookieという項目があればOKです。
Cookieの取得
Cookieについては、全てが必要ではありません。Developerツールで確認したように、レスポンスヘッダにあるSet-Cookieと実際にブラウザがセットしたCookieを比べて見てみましょう。
左側のSet-Cookieのうち、赤い枠内の部分が実際にブラウザが送信している部分です。これを取得するには、各Set-Cookieはセミコロンで区切られているため、最初のセミコロンまでを取得すれば良い、ということになります。また、右側のCookieですが、一部のデータ(赤枠内)は必要ありませんでした(試してみた結果論です)。
ワークフローの詳細は比較的基本的なツールで事足りているため説明しませんが、
- 列分割ツールを使い、改行(\n)でDownloadHeadersフィールドを行に分割
- フィルターツールでSet-Cookieを含むレコードだけ抽出
- 列分割ツールでコロンで分割後、さらにセミコロンで分割
- データクレンジングツールなどで前後の空白をトリム
- 集計ツールで複数のCookieを結合。連結の際の区切り記号は「;」(セミコロン)とする
という手順です。この手順はおそらくマクロ化して再利用可能かと思われます(いくつかのサイトで同じ手順を使いました)。
Payloadの作成
Payloadの作成はサイトによって異なります。Developerツールで見たPayloadは実はさらに整形が必要です。というのが、これはそもそもDeveloperツール側で見やすくなるように加工されたものです。実際に送信しているデータが見たい場合は、Developerツールで「ソースを表示」をクリックしてください。
「ソースを表示」をクリックすると以下のような画面が出てきます。これが実際に送信しているPayloadです。
よく見ると、、、項目名と値はコロンではなく「=」(イコール)で結合されています。各項目同士は「&」で結合されていることがわかります。さらに、値の方はURLエンコードされています。
3つの項目「authenticity_token」「timestamp」「timestamp_secret」はDownloadDataから取得する必要があります。基本的には、それぞれ正規表現ツールでDownloadDataから抜き出すのが簡単です。例えば今回は「authenticity_token」であれば以下のような設定としています。
これら以外の固定の項目は、テキスト入力ツールにセットしています。
各項目はユニオンツールでまとめて、フォーミュラツールを使い、値はURLエンコードしています。
これにより以下のような値を出来上がります(スペースの都合上一部のレコードのみ表示しています)。
これを集計ツールで区切り文字を「&」にして結合します。ワークフローとしては以下のような形になります。
これで送信すべきPayloadとCookieができあがります。
ログインする
それでは実際にログインしてみましょう。https://github.com/session にアクセスしてCookieとPayloadを使ってログインします。
ログインURLはフォーミュラツールで作ります。あとは、それぞれダウンロードツールにセットしてログインします。
ログインが成功すればDownloadHeadersに「HTTP/1.1 302 Found」などの表示が出ます(ヘッダーを見ていくとHTTP/1.1 200 OKも確認できると思います)。Designerはリダイレクト後のデータをダウンロードしてくれます(ここは自動的に行われているようです)。
さらに、レスポンスヘッダから新しいCookieが取得できるので、最初のアクセスと同じ手法でSet-CookieからCookieを作りましょう。これより後のアクセスではこのCookieを使えばおそらく問題ありません(が、サイトによっては毎回新しいCookieが発行されている可能性もあるのでご注意ください)。
おめでとうございます、これで無事にDesignerでログインができました。
アップロードされているファイルを取得する
ログインができればあとはこのCookieを使って自由にできる、といっても過言ではありません。ここからはさらにWEBサイトの作りで大きく変わりますが、欲しいファイルのURLがわかってしまえば直接アクセスしてみるのが一番の近道です。URLがわからない場合は、またDeveloperツールで探っていく必要があります。GitHubの場合は結論的には直接ほしいファイルのURLを叩けばすぐにファイルの取得ができましたが、URL自体は表に出ていないためDeveloperツールで探索する必要がありました。実際にやってみましょう。
ブラウザでまず試してみる
これもまずはブラウザのDeveloperツールで試してみましょう。
今回は、私がテスト用に作成したプライベートレポジトリを使います。レポジトリ名は「testrep」です。これをクリックしてみましょう。
以下のようにリポジトリの中に入ります。
ここで、testprepリポジトリの中のtestfileというファイルをダウンロードしたいとします。さらにtestfileをクリックしてみましょう。
適当に作ったファイルだったので、中身には「test」としか書かれていません。
もちろん、レスポンスの中身をスクレイピングすればデータを取得することは可能ですが、GitHubはファイルとしてダウンロードできるので、ダウンロードしてみましょう。WEBサイトの3点メニューからDownloadを選択することで、ファイルがダウンロードできます。
ここで、画面上に何も出てこない、という方がいらっしゃるかもしれません。ネットワークパネルのフィルタがこれまでは「ドキュメント」でほしいやり取りが見えていましたが、ここでは「すべて」にしています。サイトの中に入ってくると「ドキュメント」では見えないURLが利用されていることがあるので要注意です(ここでは「Fetch」内で確認できるデータが使われていました)。
ブラウザのファイル保存メニューなども出ますが、そのまま保存してください。Developerツール上では、以下のスクショのように一番最後の「testfile」が実際にダウンロードする際のURLとなります。ここをAlteryxで叩けばオッケーです(試した結論としてこのURLでオッケーだった、ということです。サイトによっては直接このURLを叩けない可能性もあるのでご注意ください)。
Designerでファイルのダウンロードに挑む
ログインできていれば、ログイン成功時のレスポンスヘッダーで帰ってきているSet-Cookieを使ってさらにアクセスしていきます(すでに実施済みの部分です)。アクセス用のURL「https://github.com/ayx-test/testrep/raw/refs/heads/main/testfile」をフォーミュラツールで作りましょう。あとはダウンロードツールにセットすればオッケーです。このURLの構成はパターンぽいので、他のファイルを取得したい時はこのURLを参考にすればわざわざ同じような手法で探索しなくても良さそうです。
設定としては、ヘッダーにCookieとuser-agentをセットし、HTTPアクションとしては「GET」をセットすればオッケーです(GETの場合はヘッダーのみのセットなので、URLとヘッダーに気をつければオッケーです)。
ダウンロードする部分のワークフローとしてはわずか2ツールで解決しています。
結果を見ると、実際にデータが取れていることがわかりますが、ここでもヘッダーが302なので実際にはリダイレクトがかかっています。
ブラウザの場合は手動でファイルの保存先を決めていましたが、DesignerではDownloadDataに自動的に格納されます。データが取得できてしまえば、あとはファイルとして保存するなりお好きにご利用ください。
注意点
気をつけないといけない点として、あくまでGitHubではこのようにデータが取れた、ということで、他のサイトだと色々と経由していかないといけないかもしれません。ここは各サイトに応じて実装してください。場合によってはログインと同じようにHidden属性の値をセットしてPayloadでPOSTなどしないといけないケースもあるかと思います。例えば、XX月のデータをプルダウンメニューから選択してからダウンロードボタンをクリックするようなケースでは、POSTになると思われるため、Payloadのセットなどが必要になります。今回は一番単純な内容でした。
サンプルワークフローダウンロード
注意:
- アクセスするGitHubのアカウントはデフォルトセキュリティ設定で多要素認証などは利用していません
- 2024/11/4時点のGitHubに対してログインが可能なことを確認しています
- 事前に本ワークフローを動作させるPCで一度GitHubにログインをしていることが必要になります(GitHubは異なるデバイスからのログインがあった場合、別途認証が必要になります)
- ノーサポートでお願いします
まとめ
本ブログの内容は以上となります。非常に長い内容でしたがいかがでしたでしょうか?
ある時、DB的に情報を乗せているサイトを解析していたとき、表のHTMLファイルに情報が乗っていないけどどこからデータが来ているんだ、と、JavaScriptがHTMLの裏でどのようにデータを取っているか、Developerツールのネットワークタブでやり取りを見れることを知ったのが今回のブログの一つのきっかけというのは間違いないです。
さらに、これまでいくつもAPIでのアクセスを行ってきましたが、よくよく考えたらクレデンシャルの取り方がCookieでやっているか、専用のエンドポイントでやっているか、というのが違いなだけで、WEBのログインもAPIのログインも同じじゃない?という発想からやってみたらできたということです。
ログイン時にPOSTで送信するデータは基本的にWEBサイトに埋め込まれている事が多いので、それほど苦労せずにPOSTするペイロードを作成することは可能かと思います。
ただ、Gmailのように動的に情報を扱うサイトは、ほしい情報を得るのは結構難しいです(私もまだできていません)。また、SSOなどを利用している場合のケースもまだ行ったことがありません(が、そもそもGitHub自体がAdvent of Codeのサイトに対してSSO的に動くので問題ないかもしれません)。今回の内容はまだまだチャレンジしがいのある内容ですが、基本的には本記事の内容でログインし、アクセスできるかと思います(WordPressとGitHub、あとあるサイトへのログインからファイルの取得までできているため、複雑でなければある程度この内容で通用するのではないかと思います)。
この一連の作業ですが、APIへのアクセスを行ったことがある方はおわかりかもしれませんが、APIの場合はログイン用のエンドポイント(URL)にHeader情報を付加してアクセスし、その後入手したクレデンシャルを使って各エンドポイント(URL)にアクセスしていくということになります。これ、今回行った作業と何が違うのでしょうか?URLにアクセスしてクレデンシャルを取得し、また別のURLに接続していく、という一連の作業はまったく同じです。大きく異なるのは、APIはマニュアルがありますが、今回のケースではマニュアルがない、ということです。ですので、APIアクセスの根本的なところを理解していれば、今回のようなケースもなんとかなるのではないかと思います。
コメント