はじめに
Webサイトからスクレイピングする際、テストのために多くのリクエストを飛ばしてしまい、相手に迷惑をかけてしまう恐れがあります。
Rubyでは、VCRというgemがあり、1度投げたリクエスト結果をローカルのファイルに保存しておいて、再度同じリクエストが投げれられた場合に保存したファイルを参照しにいくという便利なものがあると噂に聞きました。
ちょうどPythonでスクレイピングのコードを書いていた私は、これのPython版がないか探したところ、見つけた&使ってみて感動したので記事を書くことにしました。
Python版VCR - vcrpy
公式ドキュメントにThis is a Python version of Ruby’s VCR library.
と書いてあるあたりが、まさに求めていたものですね。
VCRとは?
VCR 【Video Cassette Recorder】
主にアメリカで使われる言葉で日本でのVTRと同じ。 家庭に普及しているVHS等のカセットに入ったテープを使用するVTRのこと。
なるほど。公式ドキュメントのイメージ画像がVHSのカセットテープなのもなっとくです。
使い方
メソッドの上に@vcr.use_cassette()
と書くだけです。
これだけで、対象のメソッドから呼ばれるrequestsの結果をファイルに保存してくれます。
デフォルトだと、実行ファイルと同ディレクトリ上にrequestsの結果のyamlファイルを保存します。
保存先のディレクトリを変更したい場合やyamlではなくjsonでファイルを保存したい場合、保存方法やVCR対象のrequestsを選びたい場合は、以下のように設定を変更できます。
my_vcr = vcr.VCR(
serializer = 'yaml',
cassette_library_dir = 'vcr',
record_mode = 'once',
match_on = ['uri', 'method'],
)
@my_vcr.use_cassette()
def hoge():
requests.get('https://qiita.com')
テストで使ってみる
qiita.comのrequests結果が一致することを確認するテストを書いてみます。
import requests
class Hoge():
def __init__(self):
pass
def getQiita(self):
r = requests.get('https://qiita.com')
return r
import pytest
import requests
import vcr
import hoge
# 保存先をvcrフォルダに変更
my_vcr = vcr.VCR(
serializer = 'yaml',
cassette_library_dir = 'vcr',
record_mode = 'once',
match_on = ['uri', 'method'],
)
@my_vcr.use_cassette()
def test_hoge(mocker):
r = requests.get('https://qiita.com')
# requestsの結果をMockを使って埋め込む
responseMock = mocker.Mock()
responseMock.text = r.text
mocker.patch('requests.get', return_value=responseMock)
h = hoge.Hoge()
hoge_r = h.getQiita()
assert r.text == hoge_r.text
テストコードでqiita.comのrequests結果をVCR化して取得します。
その結果をrequests.get
に対して、Mockでpatchを当てます。
これでtest_hoge.py
はVCR化が完了。hoge.py
はtest_hoge.py
から取得したrequests結果を参照しているので、多くのリクエストを飛ばして相手に迷惑をかけることが無くなります。
いやぁ、便利だっ