ことの始まり
python3を使って書いたあるページをクローリングするプログラムを動かしていたら
ある日こんなエラーが返ってくるようになった。
Access to XMLHttpRequest at 'https://target' from origin 'https://xxxxxxxxx' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
その時の実装は以下の通り。
import requests
res = requests.get("https://target") # webapiのURL
クローリングのターゲットとしていたページはbootstrapなんかでデータを読み込んで表示するようなページで、
レンダリング中にbootstrapから呼び出されているwebapiをターゲットにクロールしていた。
解決
selenium-wireを使ってクローリングする。
seleniumのwebdriverはレンダリング後のwebページしか取り扱えないがこれはレンダリング中の問い合わせの結果にもアクセスできる。
https://pypi.org/project/selenium-wire/
from seleniumwire import webdriver
driver = webdriver.Chrome()
driver.get("https://target") # TOPページのURL
for request in driver.requests:
if "xxxxx" in request.url: # 結果が欲しいURLを絞り込む条件(webapiのURL)
response_text = request.response.body.decode()
小噺
CORSってそもそも何
こちらの記事で勉強させていただきました。
https://qiita.com/att55/items/2154a8aad8bf1409db2b
なるほど、確かに必要。自分みたいなことする人がいるから。
CORSの処理をpythonで出来ないのか → 簡単にはできなそう
あまり調べてないけど簡単にはできなそう。だから諦めた。
CORSではプリフライトリクエストというのを先に飛ばしてそれから実際にGETなりPOSTなりしているらしい。
https://developer.mozilla.org/ja/docs/Glossary/Preflight_request
この記事にプリフライトリクエストは必要に応じてブラウザが自動的に発行します。通常、フロントエンドの開発者はそのようなリクエストを自分で作成する必要はありません。
と書いてあり、
ブラウザが勝手にやってくれる=飛ばし方を隠蔽されてるくさいなと諦めた。
なんかやるにしてもFetchAPIとかXMLHttpRequest使えって記事が出てくるので、javascriptで動かすしかなさそう。
NodeJSならできる → できるかも(未検証)
javascriptということで。NodeJSでFetchAPIを使えるらしい。
https://www.npmjs.com/package/node-fetch