はじめに
私が運営しているWebアプリケーションのジャンル的に、
スクレイピングでこんなページによく出くわします。
アダルトサイトとかでよく出くわしますが、通常のサイトでも(ログインまではいかないが)強制的にクッションサイトに飛ばされることがあるかと思います。
この強制的にクッションサイトに飛ばされることは、指定したURLではなく、クッションページをスクレイピングすることになってしまうため、大きな問題となります。
こういったページを回避して、目的のページをスクレイピングする方法を忘記録として残しておきます。
クッションページを回避してスクレイピング
それぞれ独立しているわけではありませんが、以下の3通りで概ね解決できるかと。
- seleniumを使う
- requests.session()を使う
- クッキーを渡す
なお、本記事で解説するのは「2」と「3」です。
1. seleniumを使う
一番手っ取り早いのはseleniumでchromeやfirefoxのdriverを使うことです。
seleniumの利点は、GUI的なWebブラウザの操作ができる点。
「あるページにアクセス」→「そのページのある要素をクリック」なんてことが、Python上だけで実現できます。
seleniumの詳しい解説は結構転がっているので、本記事では割愛。
ただ、問題なのはChromeやFirefoxが無い環境では動かせないという点。
sudo権限のないCUIのレンタルサーバーとかでChromeをインストールするのは(できなくはないと思いますが)非常に厳しいです。
2. requests.session()を使う
seleniumを使わなくても、クッションページの回避程度ならrequestsモジュールのsessionで十分な場合が多いです。
import requests
from bs4 import BeautifulSoup
url_certification = 'クッションページの「はい」のURL'
url_target = 'スクレイピングしたいURL'
session = requests.session()
session.get(url_certification)
soup = BeautifulSoup(session.get(url_target).content, 'lxml')
よく使用されるrequests.getはワンタイムのアクセスですが、
上記のようにsessionを使用することで、連続したアクセスを実現が実現できます。
あと、seleniumよりも圧倒的に速いのも利点。
3. クッキーを渡す
クッションページ内の「はい」のURLが、「クッキーを生成するJavaScriptへのアクセス」だと、requests.session()だけではうまくいきません。
このような場合は「はい」をクリックしたときに生成されるクッキーをrequests.getに渡してやることで解決します。
cookie = {'abc': '1'} # 予め調べておく。
soup = BeautifulSoup(requests.get(url, cookies=cookie).content, 'lxml')
今回はパスワードやメールアドレスなどのセキュアな情報を扱うわけではないので、セキュリティ面などはあまり気にせずに書いています。
cookieの調べ方は、他の方の記事を参照してください。ある要素をクリックしたときに生成されるクッキーの値を取得するといったことは、Chromeなどの実際のブラウザや、前述のselemiumなどから調べることができます。
なお、requests.getにわたすクッキーのvalueは、str型でなければならない点に注意してください。
まとめ
seleniumは色々と高機能で楽ですが、requestsモジュールだけでも色々と実現できます。
機能・速さ・セキュリティなどを考慮して、適材適所を心がけたいですね。