データナード

機械学習と自然言語処理についての備忘録 (旧ナード戦隊データマン)

継続収集としてのスクレイピング

継続的にターゲットサイトからスクレイピングするためのいくつかの経験則をまとめた。特定のプログラミング言語に依存する話は少なくしてある。

スクレイピングの困難点

1. ターゲットサイトのhtml構造に依存する

ターゲットサイトのhtml構造に併せてターゲットコンテンツを抽出する場合、その構造が変わった場合にスクレイパーを修正する必要がある。

2. スクレイピングの効率を上げるとDoS攻撃的な挙動になる

スクレイピングのとき、並列かつ繰り返し同じサイトにアクセスすることによってDoS攻撃的になってしまうことがある。

3. ターゲットサイトからのブロックの回避

目的のサイトからコンテンツを抽出しようとするが、異常な挙動を検出されてブロックされることがある。

4. 法的な問題の回避

スクレイピングに関する法的な問題に関して回避することも一つの課題。

5. 継続的かつ自動的に収集すること

スクレイパーを継続運用することが要件にある場合、上記のすべてが問題になる。

経験則一覧

1. 生のhtmlをそのままダウンロードする

特に記事などのテキスト抽出の場合、htmlをそのままダウンロードして保存しておく。 次に、ダウンロードした後のhtml等に対して、独立に当該コンテンツの抽出スクリプトをローカルで回す。

これにより、データをダウンロードするときにhtml構造を考えなくても良くなり、継続収集がしやすい。言い換えると、ダウンロードと抽出を分離し、抽出はネットを介さずに行う。

2. htmlパーサより正規表現

htmlパーサを使わずに正規表現を使ったほうが高速な場合が多い。htmlをそのままダウンロードすることを踏まえると、htmlパーサを使わずにコードを書けるケースは多い。

URLの構造はhtmlの構造よりも変わりにくいため、URLを抽出するための正規表現を書いたほうが継続的にスクレイピングしやすい。

ちなみに、html内のURLは、基本的に絶対URLに変換することが多い。

3. ツールの使い分け

cookiejavascriptなどを要求する「難しい」サイトは、chromedriverを使うと成功率が上がる。

「易しい」サイトは、requestsやcurlなど軽量なものを使ったほうが効率がいい。

4. コンテンツ抽出の機械学習モデル

当該コンテンツ部分を抽出する機械学習モデルを作る方法がある。

ただし、ヒューリスティックであるという点と、html構造に関して時代の影響を受ける (訓練データが)。

GitHub - sugiyamath/domextract: DOM based web content extractor for Japanese websites

5. VPNやtorを使う

tor (The onion routing) のような無料のオープンソースp2pプロキシを使えば、ブロックの回避がしやすくなる。(数千程度のエンドノードが使える。)

ただし、善意の人が立ち上げているサーバであり、乱用は禁物。代わりにVPNを使う方法もある。

nordvpn.com

6. ブロック回避のための小技

  • ダウンロード速度を下げる。
  • 挙動にランダム性を含ませる。
  • UAを工夫する。 
  • cookieやjavascripを必要に応じて使う。

Note: UAをランダムに変えると不審なため、統計的に不自然さのないrequest headerを送ることを考慮する。

7. 収集パターン

f:id:mathgeekjp:20200706093238j:plain

ターゲットサイトからのスクレイピングは以下の構成になることが多い:

  • 対象コンテンツを検索する機能。
  • 検索したものからコンテンツのURLを抽出する機能。
  • 抽出したURLからhtml等をダウンロードする機能。
  • ダウンロードした生html等から必要な部分を抽出する機能。

この部分をどう組み合わせるかは複数の戦略がある。

  • それぞれの機能が次の機能へ出力を渡すパイプ・フィルターの方法。
  • それぞれの機能が出力をデータとして保存しておき、それらを非同期に参照する方法。
  • すべての機能を統合してシーケンシャルに実行する方法。

など。

「現在、大量のデータがサイトにはあり、定期的に新しいコンテンツが配信される」というサイトの場合、最初の段階ですべてのデータを取得するクローラを書き、それらの取得が終わった段階で、配信間隔と量に合わせて取得する、というパターンが多い。

8. 正しいリクエス

ログインを要求するサイト、あるいは何らかのPOST, GETクエリの送信を要求される場合、正しいデータを送るように考慮する。

9. 既存スクレイピングツール

ターゲットサイトに対する高機能なスクレイピングツールがある場合、そのツールがブロック回避などに対処していることがあり、自作する手間が減る。(twitterscraper, youtube-dl, 等)

10. アクセス時の小技

  • 基本的にリトライ回数を制限して、それを超えたらスキップする。(無限にリトライすると、収集の継続性が下がる。)
  • ダウンロード済みのURLはkey-valueストアに保存しておき、再訪を防ぐと良い。

11. ブラウザの管理

chromedriverなどヘッドレスブラウザを使う場合、確率的にブラウザに問題が生じることがあるため、ブラウザをリセット・再起動する機能をつけておくと継続性が上がりやすい。

あるいは、ドライバを管理するためのクラスを作って統合する。

12. 非エンジニアが自分で収集したい場合

非エンジニアが使う場合にportiaのようなGUIツールを使うことを検討できる。

scrapinghubはノウハウがまとまっているが、柔軟性が低く、有料で、scrapyも柔軟性が低い。

フレームワークを使わずに収集することに慣れてしまった開発者にとっては役立つことが少ないが、非エンジニアには有効。

www.scrapinghub.com

13. 自動抽出のためのツール

diffbotは「コンテンツのタイプを判定」「タイプに応じて情報抽出モデルを適用」という2つの段階によってタイプごとのコンテンツを構造的に自動抽出できる。

www.diffbot.com

14. 復旧可能性

継続収集をする場合、途中で何らかの中断がされた場合に、スクレイパーが再起動される必要がある。以下を考慮すると継続収集しやすい:

  • 全エラーを時間とエラー内容でログを残す。ログを残すときは、関連するパラメータも残せるようにする。
  • 訪問したURLとその時間をログで残したり、key-valueストアに保存しておく。
  • エラーが発生する可能性のある部分すべてで、すべての例外を捕捉し、同一の方法で詳細を記録するようにする。
  • スクレイパーの起動状態を監視し、問題が生じたらアラート(メールなど)を送る。
  • 再訪を防ぐためのkey-valueストアを利用してスキップする。

15. ハードウェア上の問題の回避

収集対象のデータの量やサイズが多い場合、ハードウェア面で考慮することはある。

  • ネットワークとストレージの可用性。
  • 十分な量のメモリとストレージ。
  • 並列化するために十分なコア/ノードが使えること。

これらを解決する最も簡単な方法の一つがAWSを使うこと。

Note: NFSに対する大量のIOを発生させることはストレージの可用性を下げる。