こんにちは、しらすです。
前回、AmazonのWebサイトをスクレイピングしようとしましたが、Amazon側のスクレイピング対策により、動作が不安定な状態でした。
今回は対応策を発見したのでそれを実行していきたいと思います。
そもそもなぜ動作が不安定か?
もともとアクセス時に問題になっていたのは、以下の部分でした。
html = urllib.request.urlopen(url)
この部分が8割ほどの確率で「HTTPError: 503 Service Unavailable」となってしまいました。理由を調査した結果、この方法でアクセスするとブラウザを経由せずpythonプログラムが直接Webサイトを見に行きますが、実はAmazonなどではこのようにブラウザ経由でないアクセスをはじくようになっているようだとわかりました。
これは、アクセスを人間だけに限定したいと思ったとき、人間はほとんどの人がブラウザ経由でアクセスしますが、機械は様々なアクセス方法が可能なため、ブラウザ経由のみを許可すれば機械のアクセスのみ効率的にアクセス拒否できるというのが前提になっているためと推定されます。
さて、ここで思いつく対策は「機械でもブラウザ経由でアクセスすればよいのでは?」ということです。
Seleniumを使おう!
ということで、Seleniumを使います!Seleniumはプログラムでブラウザの操作をおこなうためのツールセットのため、ブラウザ経由でサイトにアクセス可能です。
Seleniumを使うにはライブラリのインストールとwebdriverのダウンロードが必要になります。設定は以下ご参照ください。
Seleniumを使ったコード改良
htmlを取得する部分をrequestからSeleniumに変更します。以下変更版のコードです。
[2021/08/08 追記]
BeautifulSoupライブラリの呼び出し、変数urlにyahooのページを指定
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
def get_page_from_amazon(url):
text = ""
# ヘッドレスモードでブラウザを起動
options = Options()
options.add_argument('--headless')
# ブラウザーを起動
driver = webdriver.Chrome("chromedriver.exe", options=options)
driver.get(url)
driver.implicitly_wait(10) # 見つからないときは、10秒まで待つ
text = driver.page_source
# ブラウザ停止
driver.quit()
return text
url = 'https://www.yahoo.co.jp/'
html = get_page_from_amazon(url)
soup = BeautifulSoup(html, 'lxml')
以下のサイトを参考にしました。
使ってみた結果
エラーなく情報を取得することができました!ただし実行時間はrequestを使っていた時より倍近くかかりました。改良の余地があるかまたの機会に調査してみたいと思います。
コメント
貴コードを参照して、実行した所、下記のエラーが表示されました。
エラーを検索して、解決を図りましたが自身のスキル不足で解決できません。
ご教授お願いします。
“`
html = get_page_from_amazon(url)
NameError Traceback (most recent call last)
in
—-> 1 html = get_page_from_amazon(url)
NameError: name ‘url’ is not defined
“`
urlにはご自分がhtmlを取得したいページのURLを格納する必要があります。(以下のよう)
url = ‘https://www.yahoo.co.jp/’
コード更新しましたのでご参考ください。