【Python】スクレイピングで配慮している重要ポイント

seleniumによるHTML解析を10倍速くした方法 スクレイピング

スクレイピングや自動操作を禁止していないWEBサイトでも、配慮が必要と考えています。ページ読み込みにランダムで5~20秒ほど空けるといったサーバに優しいのはもちろんですが、他にもあります。それをしなければ、サイト運営者に配慮した作りにしなければ、せっかく作ったものも短命に終わります。それどころか、アカウントBANが確定し永久追放すらあるのです。

また、WEBページのデザイン変更は何度も起こります。あるサイトでは、半年に一度に軽微なデザイン変更なされ、大きなものは一年に一度あります。そして、その都度、実装を変更しなければなりませんでした。このようなサイトをターゲットするスクレイピング案件では、特に気を配りました。半年に一度、信頼を失いかねないからです。

ここでは、零細企業や個人が発注するようなスクレイピング案件を受注するにあたり、実装上の重要ポイントに絞り参考になりそうなものを載せました。ちなみに、私のスクレイピング歴は、C#.NETとPythonで10年近くになります。

ページ遷移で注意している事

人がブラウザを操作するようにデータを取得するようにしています。バレないようにではなく、マナーだからです。よって、適切な技術選択は、外部からブラウザを操作するものになります。ライブラリは、Selenium / Pyppeteer / Requsts-HTMLでできますが、ここではSeleniumで話を進めます。

運営者は、どこをクリックして、どのページに移動したのかを見たくなります。また、A/Bテストといって、2つのデザインをランダムで表示し、クリックされたか反響をみることがあります。そのような理由でアクセス解析をすると、人の操作では起こりえない現象を目にすることがあるのです。その原因にスクレイピングがなりかねません。多少は許されるでしょうが、迷惑行為であることには違いありません。

マナー違反を犯すと、デザイン変更という形でしっぺ返しを受けるでしょう。そのため、人が操作するようにデータ取得するようにしています。

WEBページをGETでRequestしない

検索結果の表示のURLがクエリ文字列で分かり易くなっているものがあります。

https://hogehoge.jp/?keyword=キーワード&page=2

分かるからといって、3ページ目を下のようなURLでGetして、スクレピングするような事はしていません。

https://hogehoge.jp/?keyword=キーワード&page=3

直接URLを指定すると、それがアクセス解析者の目に留まります。そして、不自然なページ遷移だと見られますので、HTMLタグをclick()する方法を取っています。Seleniumでは、遷移するページへのリンクのaタグのIDに”next”が設定されている場合、次のようにして遷移します。

from selenium import webdriver

webdriver.get('https://hogehoge.jp/')
webdriver.find_element_by_css_selector("a#next").click()	#	

こうするのは迷惑行為をしないためだけではなく、HTMLの作りが変更に備えらるからです。最初はaタグの中にリンク先があっても、対策によってJavaScriptによる遷移に変わることがあります。下のように変更されたHTMLを目にしています。

<a id="link0" href="javascript:void(0)" onclick="MyMove()">LINK</a>

これはaタグをマウスでクリックすると、hrefでリンク先に遷移せず、JavaScriptの関数のMyMove()でリンク先に遷移するものです。click()で遷移すれば、hrefやJavaScriptを問わず正常に動作します。こちらの方が手間がありません。

画面外のリンクをクリックしない

Seleniumを使っていれば、https://posipochi.com/2021/04/03/python-scraping/でも触れているように、マウスでクリックできない筈の画面外のタグをclick()できる方法があります。

webdriver.execute_script("arguments[0].click();",tag)	# tagは画面外に位置する

しかし、このような回避策よりも、スクロールしてクリックする方法を取っています。JavaScriptでクリックしたタグ情報をサーバに送っている可能性があり、各種座標を含められるからです。もしブラウザの表示領域外をクリックして、ページ遷移したら解析者はどう思うでしょう。

適切な画面サイズでブラウザを制御する

スクレイピングする際、操作を受けるブラウザを小さく表示したい時があります。しかし、PCの大きなディスプレイで、わざわざブラウザを小さくしてスクレイピングすると、サイト運営者から不審に思われます。

ディスプレイの解像度(スクリーンサイズ)やブラウザでページを表示できる幅(クライアント領域)は、JavaScriptで取得でき、サイト運営者はOSと共に知ることができます。何もしなけば、スクリーンサイズもクライアント領域サイズも分かりません。しかし、WEBの商用利用において、ユーザが見ているものや動きを見ることは当然します。取得していると考えた方が自然です。

それにも関わらず、PCでスクロール多発をするようなブラウザ操作をして良いのでしょうか。そのため、小さい画面でブラウザを操作したきは、UserAgentを設定してブラウザを制御する方法を取っています。

from selenium import webdriver

options = webdriver.ChromeOptions()
options.add_argument('--user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko)')
driver = webdriver.Chrome(chrome_options=options)

スクレイピングの受注案件は、ページのデザイン変更を前提にしています

業務としてスクレイピング案件を受注した場合、取得するタグをユーザーに委ねる実装もありますが、責任が不明瞭になるため、ユーザーから求められない限りはしない方が良いと考えます。そうなると、ページのデザイン変更に速やかに対応できる実装にしなければなりません。

WEBデザイン変更に応えられるソースコードとは

HTMLから目的の値を持つタグの取得に、XPathやCSSセレクターの利用するといいです。特に間違いが少ないのは、CSSセレクターです。タグの特定のめCSSセレクターに渡す値は、Chromeデベロッパーツールで得られます。SeleniumのCSSセレクターは次のように書きます。

elem = driver.find_element_by_css_selector('.mdBrowseHistoryExpand.elPattern-B .elItem .elList>li .elPrice em')

Chromeデベロッパーツールの”Elements”タブで検索するタグを見つけ、styleタブでCSSセレクターに渡す引数を設定しています。つまり、上の引数はコピー&ペーストです。これで間違いを犯す可能性を下げます。そして、ページのデザインが変更された場合、CSSセレクターに渡す引数をデベロッパーツールで取得し直すだけで済みます。

また、CSSセレクターで目的のタグが見つからない場合もあります。このような時、ユーザーが見逃さないように配慮する必要があります。対策の例としては、try-exceptionで例外をキャッチして、ログに残す方法があります。Pyhonの標準ライブラリであるloggingでも十分ですが、ユーザーの意識が向かいやすいようにした方が良いです。

取得したデータの整合性の確認をする

取得したデータが本当に欲しいデータなのかチェックしています。次のように商品に4880円がついているとします。

<dd class="elPrice"><em>4,888円</em></dd>

これを先ほどのCSSセレクターで取得します。

elem = driver.find_element_by_css_selector('.mdBrowseHistoryExpand.elPattern-B .elItem .elList>li .elPrice em')

elem.textで文字列”4,880円”が得られますが、この値は本当に商品の価格なのでしょうか。”4,880円”を正規表現に掛けて確認します。

  • 文字列の最後に”円”付いている事
  • 最初の文字が1~9である事
  • 3桁毎にカンマが入っている事

これらを確認したうえで、価格が妥当性のあるものか商品名から自動で確認しています。

もし一覧表のようなものならば、各値と合計値が一致するか確認します。GDPの一覧表のようならものなら、各国の合計と地域の値が一致する筈です。

DB更新やCSV上書きの前に自動でバックアップ

誤ったデータを入れてしまう可能性がありますので、常に元に戻せるように、バックアップを自動で行い、それからスクレイピングを開始しています。WEBページのデザインは常に変化するため、誤ったデータが入るのを前提にしています。

スクレイピングで犯した失敗

これまで配慮を重ねてきましたが、意識が足らず誤った実装にしてしまったこともあります。そのために、危うくアカウントBANになるところでした。運営から「自動操作・取得を禁止」と注意を受けたのです。そして、そのサイトのために作った全ツールを破棄しました。

サーバメンテナンス中にスクレイピングをしてしまった

サーバメンテナンス中なのに、繰り返し繰り返し、サイトにアクセスしてログインしようとする実装していました。3分に一度のペースのアクセスです。メンテナンス中であろうがなかろうが、ログイン失敗の画面に違いはありません。そのためでした。しかし何度も失敗したら、メンテナンス中かどうか確認するために他のURLを見るべきでした。

WEBからのレスポンスがない場合のリトライの回数が多すぎた

WEBサーバにHTMLを取得してレスポンスが遅い場合、直ぐにリトライを掛けていました。正確には覚えていませんが、リクエスト10秒で諦め、そして3秒後にリトライといった時間間隔の実装です。サーバが重いのですから、迷惑行為そのものです。

同じWEBサイトにスレッドで同時アクセスしてしまった

1つのWEBサイトのあるページのデータを2秒おきに取得し、同時に別のページデータを10秒域に取得し、更に手動でページを見ていました。しかも、ほぼ一定間隔で、上から順番に見るような行儀のよい作りです。人がしていると言い逃れできないような操作です。注意を受けるだけで本当に良かったです。

コメント

タイトルとURLをコピーしました