「このサイトの情報を毎日集めて、一覧にしたい」。この相談で最初に確認するのは、技術的に取れるかどうかではありません。取ってよいのかどうかです。相手のサイトの利用規約に自動取得を禁じる条項があれば、実装できるかどうかとは無関係に手を出せません。そのうえで、robots.txtで開かれている範囲か、取得の頻度と件数が相手のサーバーに負担をかけない水準かを見ます。ここを飛ばして作った仕組みは、動いているあいだも常にリスクを抱え続けます。先に書いておくと、検索順位を人為的に動かす目的の仕組みと、相手のサービスに過負荷をかけることを目的とした大量アクセスは、技術的に可能かどうかにかかわらずお受けしていません。
法律の話は、3つの層に分けると整理できる
「スクレイピングは違法ですか」という質問には、一言で答えられません。関係する話が3層に分かれていて、それぞれ別の判断になるからです。
1つ目が著作権です。著作権法には情報解析のための利用を認める規定(第30条の4)があり、収集した情報を解析の目的で複製する行為には一定の余地があります。ただしこれは「集めてよい」であって「そのまま公開してよい」ではありません。取得したページの文章や画像を自社サイトにそのまま載せれば、それは複製と公衆送信の問題として別に評価されます。
2つ目が契約です。利用規約は著作権とは別の枠組みで効きます。「プログラムによる自動的なアクセスを禁止します」と書かれているサイトから取得すれば、著作権の話がどうであれ規約違反になり得ます。会員登録してログインした先のページであれば、規約への同意が明確なぶん、より強く効きます。
3つ目が、相手の設備への影響です。処理しきれない量のアクセスを送れば、結果として相手の業務を止めることになります。2010年に、公立図書館の蔵書検索システムへプログラムから連続してアクセスした人が逮捕され、後に起訴猶予となった事例が国内で報道されました。送っていた量そのものは大きくなく、相手側システムの実装に問題があったことが後に指摘されていますが、それでも一度は身柄を拘束されています。「自分は常識的な範囲だと思っていた」は基準になりません。
最終的な判断は弁護士に確認してください。ここで書けるのは、実装する側として引ける線までです。その線は、規約を読む、robots.txtを見る、間隔を空ける、公式の手段があればそちらを使う、の4つに集約されます。
取り方の選択肢は5つ
| 手段 | 規約上の安全度 | 壊れやすさ | JSで描画されるページ | 費用の出方 |
|---|---|---|---|---|
| 公式API | 最も高い。利用条件が明文化されている | 低い。仕様変更は告知される | 関係なく取得できる | 実装は軽い。利用料が発生する場合あり |
| RSS・CSVなどの配布データ | 高い。配布そのものが許諾 | 低い | 関係ない | 最も安い |
| HTMLの取得と解析 | 規約とrobots.txt次第 | 高い。相手のHTML変更で無言で壊れる | 取得できない | 安いが保守が続く |
| ヘッドレスブラウザで描画してから取得 | HTML取得と同じ判断 | 高い。加えて描画側の仕様変更も受ける | 取得できる | 外部サービス利用なら従量課金 |
| 人が手で転記する | 問題は生じにくい | — | — | 件数と頻度に比例して増え続ける |
順番としては上から検討します。公式APIがあるのに、わざわざHTMLを取りにいく理由はありません。APIは仕様が明示されていて、変更があれば告知され、利用条件も書かれています。「APIがあるかどうか」を調べないままHTML取得の見積りを出してくる相手には、その理由を聞いてみてください。
実際にあった判断:そもそもHTMLに載っていなかった
急上昇の検索ワードを毎日取得して、それを起点に別の処理へつなげたい、という相談を受けたことがあります。調べると、対象のページは表示されるときにブラウザ側で内容を組み立てる作りになっており、単純にHTMLを取得しても目的の値がどこにも入っていませんでした。取得できるかどうかの検証を実装より先に置かないと、着手してから作り直しになります。
費用を決めているのは取得処理そのものではなく、「いつ実行するか」と「取った結果をどう使うか」のほうです。「①から取得して、②でそれを使って検索し、③の結果を開く」といった複合的な要望は、サーバー側だけでは完結しません。ブラウザで新しいタブを開く部分は人の操作か別の仕組みが必要になるため、どこまでをサーバー側でやるのかを最初に切り分けます。この案件は予算が合わず、動くソースを納品する形と、やり方をお伝えする形に金額を分けて提示し、後者で着地しました。
実際にあった判断:JavaScriptで描画されるページを取る
ブラウザ上のJavaScriptで動いていた取得処理を、サーバー側のPHPに移したいという依頼を受けたことがあります。対象は、JavaScriptで内容が描画される大手サービスの商品ページでした。ここで踏んだ点は、他のサイトでもそのまま使えます。
まず、単純にHTMLを取りにいくと500が返りました。原因はリクエストヘッダで、3つ足したら通っています。Accept-Encoding: identity で圧縮を無効にすること、ブラウザと同じ User-Agent を送ること、そして Referer を付けることです。大手のサイトで500や403が返るときは、まずこの3点を疑ってください。なお、これはアクセスを拒否されているサイトに無理やり入るための手順ではありません。取得が許されている前提で、通常のブラウザと同じ形のリクエストを送るという話です。
描画にJavaScriptが必要なページは、ヘッドレスブラウザをAPIとして提供している外部サービスに投げる形にしました。PHP側の実装は file_get_contents と stream_context_create の組み合わせでPOSTすれば足り、cURLは使っていません。ここで時間を取られたのは細部です。パラメータの renderType は大文字小文字を区別し、HTML では通らず html で通りました。そして最も厄介だったのが、json_decode したオブジェクトをもう一度 json_encode して渡してしまい、その後のノードアクセスがすべてNULLになる、という状態です。「ノードが無い」という不具合の最頻出の原因がこれなので、関数の戻り値がオブジェクトなのかJSON文字列なのかを明示して受け渡してください。
文字化けの対策も定型があります。mb_detect_encoding に候補の配列を渡して判定し、判定に失敗したらShift_JISへフォールバックする。この形をそのまま使い回しています。文字コードの扱い全般はCSVの取り込みで文字化けを起こさないための処理と、確認の手順にまとめました。
デバッグでの注意点をひとつ。取得したHTMLを var_dump で画面に出すと、そのHTMLがブラウザで描画されます。ポップアップやスクリプトが動いて画面が操作不能になることがあるので、ファイルへ書き出すか htmlspecialchars() で包んでから出してください。実際にこれで詰まった例があります。
出力側を変えたら、受け側も直る前提で見積もる
取得した結果を別のプログラムへ渡す構成では、出力の形式も設計対象です。PHPでXMLを返すなら、echo による文字列の連結ではなく SimpleXMLElement で組み立ててください。エスケープと文字コードとヘッダーの扱いが自動化され、受け側でのパース失敗が目に見えて減ります。
そして、出力形式を変えたら受け側の読み込み処理もセットで直します。工数の感覚としては、出力側の修正が1なら受け側は2くらいです。実際、出力側の改修依頼として受けた案件で、時間の大半は受け側の調整に消えました。同じツールが複数のサーバーに設置されている場合はさらに注意が要ります。1台で動いたからといって他の台で動くとは限らず、実際に文字コード起因の障害が別の台で後から出ました。設置場所の一覧を先に確認してください。
負荷は、件数ではなく間隔で決まる
実測を1つ出します。800件を超えるページを順に取得する仕組みで、全体の所要は6分弱でした。1件あたり0.4秒ほどです。相手のサーバーから見れば、これは0.4秒に1回アクセスが来ている状態になります。1件ごとに1秒の待ちを入れれば、850件でも15分程度。夜間に回すのであれば、この差は業務上ほとんど影響しません。相手にとっては大きな違いです。
同時に複数のリクエストを投げる並列処理は、速いぶん相手からは攻撃と区別が付きません。件数が多くても順次実行にして、待ち時間を挟む。User-Agent に用途と連絡先を書いておけば、相手が困ったときに問い合わせ先が分かります。これらは技術的な最適化ではなく、続けられる形にするための条件です。実行の組み方そのものはcronで毎日の集計と通知を自動化するのほうに書いています。
依頼する前に決めておくと、費用が下がるもの
- 対象URLの一覧。何件あるか、増える見込みがあるか
- 取りたい項目。ページのどこに書かれているかも指し示せると早い
- 実行の頻度と時刻。毎日なのか、週1なのか、手動で回すのか
- 取った結果の使い道。CSVで落とすのか、サイトに表示するのか、別システムへ渡すのか
- 壊れたときにどうしたいか。止まったことに気づく仕組みを含めるか、含めないか
5つ目を決めておくかどうかで、見積りは変わります。HTMLの構造に依存する取得は、相手が変更すれば必ず壊れます。エラーも出さず、ただ値が取れなくなる形で壊れることが多いので、取得件数が0の日が続いたら通知する、といった仕組みを最初から入れておくのが現実的です。作った時点で完成する仕組みではなく、相手のサイトが変わるたびに手が要る仕組みだ、という前提で発注してください。
よくある質問
robots.txtで許可されていれば、取得してよいということですか
robots.txtはクローラー向けの案内であって、許諾そのものではありません。利用規約に自動取得の禁止が書かれていれば、robots.txtがどうであれ規約が優先します。逆に、robots.txtで拒否されている領域を取りにいくのは、規約に明記がなくても避けるべきです。両方を見たうえで、どちらかが否定していれば手を出さない、という判断にしています。
取得したデータを自社サイトに載せてもよいですか
社内で参照するために集めることと、集めたものを公開することは別の話です。文章や画像をそのまま載せれば著作権の問題になりますし、事実の羅列であっても、まとまった量をそのまま転載すればデータベースとしての保護や不正競争の観点が出てきます。公開を前提にするなら、実装より先に法務の確認を通してください。
検索順位を上げるための仕組みは作ってもらえますか
検索エンジンに対して人為的に働きかける仕組みは、目的にかかわらずお受けしていません。順位の計測のために自動的に検索クエリを送る類の仕組みも同様です。検索結果まわりでできることは、自社サイト側の構造と内容を整えることに限られます。SEOの対応内容のほうに、実際に対応している範囲を書いています。
既存の自動化ツールでは足りませんか
取得先が主要なサービスで、件数が少なければ足ります。足りなくなるのは、HTMLの解析が必要なとき、実行回数が多くて課金が跳ねるとき、そして失敗した分を自前で再実行したいときです。判断の基準はZapierで足りなくなったとき、自作APIブリッジに切り替える判断基準にまとめています。
取得してよいのかどうかの確認から、実際に動く形にするところまでまとめてお引き受けできます。対象のサイトと取りたい項目を伺えれば、公式の手段で足りるのか、作る必要があるのかを先に切り分けてお伝えします。
