LoginSignup
3
4

More than 1 year has passed since last update.

レンダリング中に登場するwebapiをクロールしてたらCORSで弾かれたからなんとかする

Last updated at Posted at 2020-07-30

ことの始まり

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

3
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4