Pythonのリクエストライブラリ(ガイド)

Pythonのリクエストライブラリ(ガイド)

+ requests +ライブラリは、PythonでHTTPリクエストを行うための事実上の標準です。 これは、美しくシンプルなAPIの背後にあるリクエストの複雑さを抽象化し、サービスとのやり取りやアプリケーションでのデータの消費に集中できるようにします。

この記事では、 `+ requests `が提供しなければならない最も便利な機能のいくつかと、遭遇するさまざまな状況に合わせてこれらの機能をカスタマイズおよび最適化する方法を紹介します。 また、「 requests +」を効率的な方法で使用する方法と、外部サービスへのリクエストがアプリケーションの速度を低下させないようにする方法についても学習します。

このチュートリアルでは、次の方法を学習します

  • 最も一般的なHTTPメソッドを使用してリクエストを作成

  • クエリ文字列とメッセージ本文を使用して、リクエストのヘッダーとデータを*カスタマイズ*

  • リクエストとレスポンスのデータを*検査*

  • *認証済み*リクエストを行う

  • アプリケーションのバックアップまたはスローダウンを防ぐために、リクエストを*構成*します

この記事に含まれる機能と例を理解するために必要なだけの情報を含めようとしましたが、http://www.w3schools.com/tags/ref_httpmethods.asp [HTTPの基本的な一般知識] ]。 とはいえ、とにかくうまくいくことができるかもしれません。

これで問題は解決しました。次に、アプリケーションで「+ requests +」を使用する方法を見てみましょう。

`+ requests +`の開始方法

まず、 `+ requests +`ライブラリをインストールします。 これを行うには、次のコマンドを実行します。

$ pip install requests

Pythonパッケージの管理にhttps://realpython.com/pipenv-guide/[Pipenv]を使用する場合は、次を実行できます。

$ pipenv install requests

`+ requests `がインストールされると、アプリケーションで使用できます。 ` requests +`のインポートは次のようになります。

import requests

すべての設定が完了したので、「リクエスト」を通じて旅を始めましょう。 最初の目標は、「+ GET +」リクエストの作成方法を学習することです。

GETリクエスト

https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods [+ GET + + POST + `などのHTTPメソッド]は、HTTPリクエストを行うときに実行しようとしているアクションを決定します。 `+ GET `と ` POST +`以外にも、このチュートリアルの後半で使用するいくつかの一般的な方法があります。

最も一般的なHTTPメソッドの1つは「+ GET 」です。 ` GET `メソッドは、指定されたリソースからデータを取得または取得しようとしていることを示します。 ` GET `リクエストを作成するには、 ` requests.get()+`を呼び出します。

これをテストするには、GitHubのhttps://developer.github.com/v3/#root-endpoint[Root REST API]に次のURLで `+ get()`を呼び出して ` GET +`リクエストを行うことができます:

>>>

>>> requests.get('https://api.github.com')
<Response [200]>

おめでとうございます。 最初のリクエストを行いました。 その要求の応答についてもう少し詳しく見てみましょう。

応答

`+ Response +`はリクエストの結果を検査するための強力なオブジェクトです。 同じリクエストをもう一度行いますが、今回は戻り値を変数に保存して、その属性と動作を詳しく見てみましょう。

>>>

>>> response = requests.get('https://api.github.com')

この例では、 `+ Response `のインスタンスである ` get()`の戻り値をキャプチャし、 ` response `という変数に格納しました。 これで、 ` response `を使用して、 ` GET +`リクエストの結果に関する多くの情報を表示できます。

状態コード

`+ Response +`から収集できる最初の情報はステータスコードです。 ステータスコードにより、リクエストのステータスが通知されます。

たとえば、「+ 200 OK 」ステータスはリクエストが成功したことを意味し、「 404 NOT FOUND +」ステータスは探しているリソースが見つからなかったことを意味します。 https://en.wikipedia.org/wiki/List_of_HTTP_status_codes [他の多くのステータスコード]もあり、リクエストで何が起こったのかについての具体的な洞察を提供します。

`+ .status_code +`にアクセスすると、サーバーが返したステータスコードを確認できます。

>>>

>>> response.status_code
200

`+ .status_code `は ` 200 +`を返しました。これは、リクエストが成功し、サーバーがリクエストしたデータで応答したことを意味します。

場合によっては、この情報を使用してコードの決定を行うことができます。

if response.status_code == 200:
    print('Success!')
elif response.status_code == 404:
    print('Not Found.')

このロジックにより、サーバーが `+ 200 `ステータスコードを返した場合、プログラムは ` Success!`を出力します。 結果が「+404」の場合、プログラムは「+ Not Found +」を出力します。

`+ requests `は、このプロセスを単純化するための一歩先を行きます。 条件式で ` Response `インスタンスを使用する場合、ステータスコードが ` 200 `と ` 400 `の間にある場合は ` True `に評価され、そうでない場合は ` False +`に評価されます。

したがって、 `+ if +`ステートメントを書き直すことで最後の例を単純化できます:

if response:
    print('Success!')
else:
    print('An error has occurred.')

*技術的詳細:*このhttps://docs.python.org/3/library/stdtypes.html#truth-value-testing [真理値テスト]は、https://realpython.com/operator-function- overloading/#making-your-objects-truthy-or-falsey-using-bool [+ Response +`のオーバーロードされたメソッド] [+ bool ()+`です。

これは、オブジェクトの真理値を決定するときにステータスコードを考慮するために、 `+ Response +`のデフォルトの動作が再定義されたことを意味します。

このメソッドは、ステータスコードが「200」に等しいことを確認するものではないことに注意してください。 この理由は、「+ 204 NO CONTENT 」や「+304 NOT MODIFIED +」など、「 200+」から「400」の範囲内の他のステータスコードも、それらが提供するという意味で成功と見なされるためです。いくつかの実行可能な応答。

たとえば、「+ 204+」は、応答は成功したが、メッセージ本文に返すコンテンツがないことを示します。

そのため、リクエストが一般的に成功したかどうかを知りたい場合にのみ、この便利な略記法を使用し、必要に応じてステータスコードに基づいて応答を適切に処理してください。

`+ if `ステートメントで応答のステータスコードを確認したくないとしましょう。 代わりに、リクエストが失敗した場合に例外を発生させます。 これは、 ` .raise_for_status()+`を使用して実行できます。

import requests
from requests.exceptions import HTTPError

for url in ['https://api.github.com', 'https://api.github.com/invalid']:
    try:
        response = requests.get(url)

        # If the response was successful, no Exception will be raised
        response.raise_for_status()
    except HTTPError as http_err:
        print(f'HTTP error occurred: {http_err}')  # Python 3.6
    except Exception as err:
        print(f'Other error occurred: {err}')  # Python 3.6
    else:
        print('Success!')

`+ .raise_for_status()`を呼び出すと、特定のステータスコードに対して ` HTTPError +`が発生します。 ステータスコードがリクエストの成功を示している場合、プログラムはその例外を発生させることなく続行します。

さらに読む: Python 3.6のhttps://realpython.com/python-f-strings/[f-strings]に慣れていない場合は、すばらしい方法であるため、それらを活用することをお勧めします。フォーマットされた文字列を簡素化します。

これで、サーバーから返された応答のステータスコードを処理する方法について多くのことがわかりました。 ただし、 `+ GET +`リクエストを行うとき、レスポンスのステータスコードのみを気にすることはほとんどありません。 通常、あなたはもっと見たいです。 次に、サーバーが応答の本文で送信した実際のデータを表示する方法を確認します。

コンテンツ

「+ GET 」リクエストの応答には、多くの場合、ペイロードと呼ばれる貴重な情報がメッセージ本文に含まれています。 「 Response +」の属性とメソッドを使用して、さまざまな異なる形式でペイロードを表示できます。

+ bytes +で応答のコンテンツを表示するには、 `+ .content +`を使用します。

>>>

>>> response = requests.get('https://api.github.com')
>>> response.content
b'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}","emails_url":"https://api.github.com/user/emails","emojis_url":"https://api.github.com/emojis","events_url":"https://api.github.com/events","feeds_url":"https://api.github.com/feeds","followers_url":"https://api.github.com/user/followers","following_url":"https://api.github.com/user/following{/target}","gists_url":"https://api.github.com/gists{/gist_id}","hub_url":"https://api.github.com/hub","issue_search_url":"https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}","issues_url":"https://api.github.com/issues","keys_url":"https://api.github.com/user/keys","notifications_url":"https://api.github.com/notifications","organization_repositories_url":"https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}","organization_url":"https://api.github.com/orgs/{org}","public_gists_url":"https://api.github.com/gists/public","rate_limit_url":"https://api.github.com/rate_limit","repository_url":"https://api.github.com/repos/{owner}/{repo}","repository_search_url":"https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}","current_user_repositories_url":"https://api.github.com/user/repos{?type,page,per_page,sort}","starred_url":"https://api.github.com/user/starred{/owner}{/repo}","starred_gists_url":"https://api.github.com/gists/starred","team_url":"https://api.github.com/teams","user_url":"https://api.github.com/users/{user}","user_organizations_url":"https://api.github.com/user/orgs","user_repositories_url":"https://api.github.com/users/{user}/repos{?type,page,per_page,sort}","user_search_url":"https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"}'

`+ .content `を使用すると、応答ペイロードの生のバイトにアクセスできますが、次のような文字エンコードを使用してhttps://realpython.com/python-data-types/[string]に変換することがよくあります。 https://en.wikipedia.org/wiki/UTF-8[UTF-8]。 ` .text `にアクセスすると、 ` response +`がそれを行います:

>>>

>>> response.text
'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}","emails_url":"https://api.github.com/user/emails","emojis_url":"https://api.github.com/emojis","events_url":"https://api.github.com/events","feeds_url":"https://api.github.com/feeds","followers_url":"https://api.github.com/user/followers","following_url":"https://api.github.com/user/following{/target}","gists_url":"https://api.github.com/gists{/gist_id}","hub_url":"https://api.github.com/hub","issue_search_url":"https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}","issues_url":"https://api.github.com/issues","keys_url":"https://api.github.com/user/keys","notifications_url":"https://api.github.com/notifications","organization_repositories_url":"https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}","organization_url":"https://api.github.com/orgs/{org}","public_gists_url":"https://api.github.com/gists/public","rate_limit_url":"https://api.github.com/rate_limit","repository_url":"https://api.github.com/repos/{owner}/{repo}","repository_search_url":"https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}","current_user_repositories_url":"https://api.github.com/user/repos{?type,page,per_page,sort}","starred_url":"https://api.github.com/user/starred{/owner}{/repo}","starred_gists_url":"https://api.github.com/gists/starred","team_url":"https://api.github.com/teams","user_url":"https://api.github.com/users/{user}","user_organizations_url":"https://api.github.com/user/orgs","user_repositories_url":"https://api.github.com/users/{user}/repos{?type,page,per_page,sort}","user_search_url":"https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"}'

`+ bytes `を ` str `にデコードするにはエンコードスキームが必要なので、 ` requests `はhttps://docs.python.org/3/howto/unicode.html#encodings[encoding]を推測しようとします。指定しない場合、応答のhttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers[headers]に基づきます。 ` .text `にアクセスする前に ` .encoding +`を設定することで明示的なエンコーディングを提供できます:

>>>

>>> response.encoding = 'utf-8' # Optional: requests infers this internally
>>> response.text
'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}","emails_url":"https://api.github.com/user/emails","emojis_url":"https://api.github.com/emojis","events_url":"https://api.github.com/events","feeds_url":"https://api.github.com/feeds","followers_url":"https://api.github.com/user/followers","following_url":"https://api.github.com/user/following{/target}","gists_url":"https://api.github.com/gists{/gist_id}","hub_url":"https://api.github.com/hub","issue_search_url":"https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}","issues_url":"https://api.github.com/issues","keys_url":"https://api.github.com/user/keys","notifications_url":"https://api.github.com/notifications","organization_repositories_url":"https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}","organization_url":"https://api.github.com/orgs/{org}","public_gists_url":"https://api.github.com/gists/public","rate_limit_url":"https://api.github.com/rate_limit","repository_url":"https://api.github.com/repos/{owner}/{repo}","repository_search_url":"https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}","current_user_repositories_url":"https://api.github.com/user/repos{?type,page,per_page,sort}","starred_url":"https://api.github.com/user/starred{/owner}{/repo}","starred_gists_url":"https://api.github.com/gists/starred","team_url":"https://api.github.com/teams","user_url":"https://api.github.com/users/{user}","user_organizations_url":"https://api.github.com/user/orgs","user_repositories_url":"https://api.github.com/users/{user}/repos{?type,page,per_page,sort}","user_search_url":"https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"}'

応答を見ると、実際にシリアル化されたJSONコンテンツであることがわかります。 辞書を取得するには、 + .text +`から取得した `+ str +`を取得し、https://realpython.com/python-json/#deserializing-json [+ json.loads()を使用してデシリアライズします`]。 ただし、このタスクを実行するより簡単な方法は、 ` .json()+`を使用することです:

>>>

>>> response.json()
{'current_user_url': 'https://api.github.com/user', 'current_user_authorizations_html_url': 'https://github.com/settings/connections/applications{/client_id}', 'authorizations_url': 'https://api.github.com/authorizations', 'code_search_url': 'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}', 'commit_search_url': 'https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}', 'emails_url': 'https://api.github.com/user/emails', 'emojis_url': 'https://api.github.com/emojis', 'events_url': 'https://api.github.com/events', 'feeds_url': 'https://api.github.com/feeds', 'followers_url': 'https://api.github.com/user/followers', 'following_url': 'https://api.github.com/user/following{/target}', 'gists_url': 'https://api.github.com/gists{/gist_id}', 'hub_url': 'https://api.github.com/hub', 'issue_search_url': 'https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}', 'issues_url': 'https://api.github.com/issues', 'keys_url': 'https://api.github.com/user/keys', 'notifications_url': 'https://api.github.com/notifications', 'organization_repositories_url': 'https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}', 'organization_url': 'https://api.github.com/orgs/{org}', 'public_gists_url': 'https://api.github.com/gists/public', 'rate_limit_url': 'https://api.github.com/rate_limit', 'repository_url': 'https://api.github.com/repos/{owner}/{repo}', 'repository_search_url': 'https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}', 'current_user_repositories_url': 'https://api.github.com/user/repos{?type,page,per_page,sort}', 'starred_url': 'https://api.github.com/user/starred{/owner}{/repo}', 'starred_gists_url': 'https://api.github.com/gists/starred', 'team_url': 'https://api.github.com/teams', 'user_url': 'https://api.github.com/users/{user}', 'user_organizations_url': 'https://api.github.com/user/orgs', 'user_repositories_url': 'https://api.github.com/users/{user}/repos{?type,page,per_page,sort}', 'user_search_url': 'https://api.github.com/search/users?q={query}{&page,per_page,sort,order}'}

`+ .json()`の戻り値の ` type +`は辞書であるため、オブジェクトの値にキーでアクセスできます。

ステータスコードとメッセージ本文で多くのことができます。 ただし、応答自体に関するメタデータなどの詳細情報が必要な場合は、応答のヘッダーを確認する必要があります。

ヘッダ

応答ヘッダーは、応答ペイロードのコンテンツタイプや、応答をキャッシュする時間の制限など、有用な情報を提供できます。 これらのヘッダーを表示するには、 `+ .headers +`にアクセスします。

>>>

>>> response.headers
{'Server': 'GitHub.com', 'Date': 'Mon, 10 Dec 2018 17:49:54 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Status': '200 OK', 'X-RateLimit-Limit': '60', 'X-RateLimit-Remaining': '59', 'X-RateLimit-Reset': '1544467794', 'Cache-Control': 'public, max-age=60, s-maxage=60', 'Vary': 'Accept', 'ETag': 'W/"7dc470913f1fe9bb6c7355b50a0737bc"', 'X-GitHub-Media-Type': 'github.v3; format=json', 'Access-Control-Expose-Headers': 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type', 'Access-Control-Allow-Origin': '*', 'Strict-Transport-Security': 'max-age=31536000; includeSubdomains; preload', 'X-Frame-Options': 'deny', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block', 'Referrer-Policy': 'origin-when-cross-origin, strict-origin-when-cross-origin', 'Content-Security-Policy': "default-src 'none'", 'Content-Encoding': 'gzip', 'X-GitHub-Request-Id': 'E439:4581:CF2351:1CA3E06:5C0EA741'}

`+ .headers `は辞書のようなオブジェクトを返し、キーでヘッダー値にアクセスできます。 たとえば、応答ペイロードのコンテンツタイプを表示するには、 ` Content-Type +`にアクセスできます。

>>>

>>> response.headers['Content-Type']
'application/json; charset=utf-8'

ただし、この辞書に似たヘッダーオブジェクトには特別なものがあります。 HTTP仕様では、ヘッダーは大文字と小文字を区別しないように定義されています。つまり、大文字の使用を心配することなくこれらのヘッダーにアクセスできます。

>>>

>>> response.headers['content-type']
'application/json; charset=utf-8'

キー「+ 'content-type' + 」または「+ 'Content-Type' +」のどちらを使用しても、同じ値が得られます。

これで、「+ Response 」の基本を学びました。 最も有用な属性とメソッドが動作しているのを見てきました。 少し戻って、 ` GET +`リクエストをカスタマイズしたときの応答の変化を見てみましょう。

クエリ文字列パラメーター

`+ GET `リクエストをカスタマイズする一般的な方法の1つは、URLのhttps://en.wikipedia.org/wiki/Query_string [クエリ文字列]パラメーターを介して値を渡すことです。 ` get()`を使用してこれを行うには、データを ` params `に渡します。 たとえば、GitHubのhttps://developer.github.com/v3/search/[Search] APIを使用して、 ` requests +`ライブラリを検索できます。

import requests

# Search GitHub's repositories for requests
response = requests.get(
    'https://api.github.com/search/repositories',
    params={'q': 'requests+language:python'},
)

# Inspect some attributes of the `requests` repository
json_response = response.json()
repository = json_response['items'][0]
print(f'Repository name: {repository["name"]}')  # Python 3.6+
print(f'Repository description: {repository["description"]}')  # Python 3.6+

辞書 `+ {'q': 'requests + language:python'} `を ` .get()`の ` params +`パラメーターに渡すことにより、 Search API。

あなたがやったように、またはタプルのリストとして、辞書の形で `+ params `を ` get()+`に渡すことができます:

>>>

>>> requests.get(
...     'https://api.github.com/search/repositories',
...     params=[('q', 'requests+language:python')],
... )
<Response [200]>

値を `+ bytes +`として渡すこともできます:

>>>

>>> requests.get(
...     'https://api.github.com/search/repositories',
...     params=b'q=requests+language:python',
... )
<Response [200]>

クエリ文字列は、 `+ GET +`リクエストをパラメータ化するのに役立ちます。 送信するヘッダーを追加または変更して、リクエストをカスタマイズすることもできます。

リクエストヘッダ

ヘッダーをカスタマイズするには、 `+ headers `パラメーターを使用してHTTPヘッダーの辞書を ` get()`に渡します。 たとえば、 ` Accept `ヘッダーで ` text-match +`メディアタイプを指定することにより、結果で一致する検索語を強調表示するように以前の検索リクエストを変更できます。

import requests

response = requests.get(
    'https://api.github.com/search/repositories',
    params={'q': 'requests+language:python'},
    headers={'Accept': 'application/vnd.github.v3.text-match+json'},
)

# View the new `text-matches` array which provides information
# about your search term within the results
json_response = response.json()
repository = json_response['items'][0]
print(f'Text matches: {repository["text_matches"]}')

`+ Accept `ヘッダーは、アプリケーションが処理できるコンテンツタイプをサーバーに伝えます。 この場合、一致する検索語が強調表示されることが予想されるため、独自のGitHub ` Accept `であるヘッダー値 ` application/vnd.github.v3.text-match + json +`を使用しています。コンテンツが特別なJSON形式であるヘッダー。

リクエストをカスタマイズする他の方法を学ぶ前に、他のHTTPメソッドを調べて範囲を広げましょう。

その他のHTTPメソッド

「+ GET 」の他に、他の一般的なHTTPメソッドには、「 POST 」、「 PUT 」、「 DELETE 」、「 HEAD 」、「 PATCH 」、および「 OPTIONS 」があります。 ` requests `は、これらの各HTTPメソッドに対して、 ` get()+`と同様のシグネチャを持つメソッドを提供します。

>>>

>>> requests.post('https://httpbin.org/post', data={'key':'value'})
>>> requests.put('https://httpbin.org/put', data={'key':'value'})
>>> requests.delete('https://httpbin.org/delete')
>>> requests.head('https://httpbin.org/get')
>>> requests.patch('https://httpbin.org/patch', data={'key':'value'})
>>> requests.options('https://httpbin.org/get')

各関数呼び出しは、対応するHTTPメソッドを使用して `+ httpbin +`サービスにリクエストを行います。 各メソッドについて、以前と同じ方法で応答を検査できます。

>>>

>>> response = requests.head('https://httpbin.org/get')
>>> response.headers['Content-Type']
'application/json'

>>> response = requests.delete('https://httpbin.org/delete')
>>> json_response = response.json()
>>> json_response['args']
{}

ヘッダー、応答本文、ステータスコードなどは、各メソッドの + Response +`で返されます。 次に、 `+ POST ++ PUT +、および `+ PATCH +`メソッドを詳しく見て、それらが他のリクエストタイプとどのように異なるかを学びます。

メッセージ本文

HTTP仕様によると、「+ POST 」、「 PUT 」、およびあまり一般的ではない「 PATCH 」リクエストは、クエリ文字列のパラメーターではなく、メッセージ本文を介してデータを渡します。 ` requests `を使用して、ペイロードを対応する関数の ` data +`パラメーターに渡します。

`+ data +`は辞書、タプルのリスト、バイト、またはファイルのようなオブジェクトを取ります。 リクエストの本文で送信するデータを、やり取りするサービスの特定のニーズに合わせて調整する必要があります。

たとえば、リクエストのコンテンツタイプが「+ application/x-www-form-urlencoded +」の場合、フォームデータを辞書として送信できます。

>>>

>>> requests.post('https://httpbin.org/post', data={'key':'value'})
<Response [200]>

同じデータをタプルのリストとして送信することもできます。

>>>

>>> requests.post('https://httpbin.org/post', data=[('key', 'value')])
<Response [200]>

ただし、JSONデータを送信する必要がある場合は、 `+ json `パラメーターを使用できます。 JSONデータを ` json `経由で渡す場合、 ` requests `はデータをシリアル化し、正しい ` Content-Type +`ヘッダーを追加します。

httpbin.orgは、 `+ requests `の作者であるhttps://realpython.com/interview-kenneth-reitz/[Kenneth Reitz]によって作成された優れたリソースです。 テストリクエストを受け入れ、リクエストに関するデータで応答するサービスです。 たとえば、これを使用して基本的な ` POST +`リクエストを検査できます。

>>>

>>> response = requests.post('https://httpbin.org/post', json={'key':'value'})
>>> json_response = response.json()
>>> json_response['data']
'{"key": "value"}'
>>> json_response['headers']['Content-Type']
'application/json'

応答から、サーバーがリクエストデータとヘッダーを送信したときに受信したことがわかります。 `+ requests `は、この情報を ` PreparedRequest +`の形式で提供します。

リクエストの検査

リクエストを行うとき、 `+ requests +`ライブラリは実際に宛先サーバーに送信する前にリクエストを準備します。 リクエストの準備には、ヘッダーの検証やJSONコンテンツのシリアル化などが含まれます。

`+ .request `にアクセスして、 ` PreparedRequest +`を表示できます。

>>>

>>> response = requests.post('https://httpbin.org/post', json={'key':'value'})
>>> response.request.headers['Content-Type']
'application/json'
>>> response.request.url
'https://httpbin.org/post'
>>> response.request.body
b'{"key": "value"}'

`+ PreparedRequest +`を調べると、ペイロード、URL、ヘッダー、認証など、行われているリクエストに関するあらゆる種類の情報にアクセスできます。

これまで、さまざまな種類のリクエストを数多く行ってきましたが、それらには共通点が1つあります。それは、パブリックAPIに対する認証されていないリクエストです。 あなたが出くわすかもしれない多くのサービスは、何らかの方法であなたに認証をして欲しいでしょう。

認証

認証は、サービスがあなたが誰であるかを理解するのに役立ちます。 通常、 `+ Authorization `ヘッダーまたはサービスで定義されたカスタムヘッダーを介してデータを渡すことで、サーバーに資格情報を提供します。 ここまで見てきたすべてのリクエスト関数は、資格情報を渡すことができる「 auth +」というパラメーターを提供します。

認証が必要なAPIの例の1つは、GitHubのhttps://developer.github.com/v3/users/#get-the-authenticated-user[Authenticated User] APIです。 このエンドポイントは、認証されたユーザーのプロファイルに関する情報を提供します。 Authenticated User APIにリクエストを行うには、GitHubのユーザー名とパスワードをタプルで `+ get()+`に渡すことができます:

>>>

>>> from getpass import getpass
>>> requests.get('https://api.github.com/user', auth=('username', getpass()))
<Response [200]>

タプルで `+ auth +`に渡した認証情報が有効な場合、リクエストは成功しました。 認証情報なしでこのリクエストを行おうとすると、ステータスコードが「+401 Unauthorized +」であることがわかります。

>>>

>>> requests.get('https://api.github.com/user')
<Response [401]>

タプルでユーザー名とパスワードを `+ auth `パラメーターに渡すと、 ` requests +`はHTTPのhttps://en.wikipedia.org/wiki/Basic_access_authentication [基本アクセス認証スキーム]を使用して資格情報を適用します。

したがって、 `+ HTTPBasicAuth +`を使用して明示的な基本認証資格情報を渡すことにより、同じリクエストを行うことができます。

>>>

>>> from requests.auth import HTTPBasicAuth
>>> from getpass import getpass
>>> requests.get(
...     'https://api.github.com/user',
...     auth=HTTPBasicAuth('username', getpass())
... )
<Response [200]>

基本認証を明示的に指定する必要はありませんが、別の方法を使用して認証することもできます。 `+ requests `は、 ` HTTPDigestAuth `や ` HTTPProxyAuth +`など、すぐに使用できる他の認証方法を提供します。

独自の認証メカニズムを提供することもできます。 そのためには、最初に `+ AuthBase `のサブクラスを作成する必要があります。 次に、 ` call ()+`を実装します。

import requests
from requests.auth import AuthBase

class TokenAuth(AuthBase):
    """Implements a custom authentication scheme."""

    def __init__(self, token):
        self.token = token

    def __call__(self, r):
        """Attach an API token to a custom auth header."""
        r.headers['X-TokenAuth'] = f'{self.token}'  # Python 3.6+
        return r


requests.get('https://httpbin.org/get', auth=TokenAuth('12345abcde-token'))

ここでは、カスタムの「+ TokenAuth 」メカニズムがトークンを受け取り、リクエストの「 X-TokenAuth +」ヘッダーにそのトークンを含めます。

不正な認証メカニズムはセキュリティの脆弱性につながる可能性があるため、何らかの理由でサービスがカスタム認証メカニズムを必要としない限り、常にBasicやOAuthなどの実証済みの認証スキームを使用する必要があります。

セキュリティについて考えている間、 `+ requests +`を使用してSSL証明書を扱うことを検討しましょう。

SSL証明書の検証

送信または受信しようとしているデータが機密である場合は常に、セキュリティが重要です。 HTTP経由で安全なサイトと通信するには、SSLを使用して暗号化された接続を確立します。つまり、ターゲットサーバーのSSL証明書を確認することが重要です。

幸いなことに、 `+ requests +`はデフォルトでこれを行います。 ただし、この動作を変更する必要がある場合があります。

SSL証明書の検証を無効にする場合は、リクエスト関数の `+ verify `パラメータに ` False +`を渡します。

>>>

>>> requests.get('https://api.github.com', verify=False)
InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
<Response [200]>

`+ requests +`は、データを安全に保つために安全でないリクエストを行っているときにも警告します!

注意: http://docs.python-requests.org/en/master/user/advanced/#ca-certificates [+ requests +`は `+ certifi +]というパッケージを使用して認証局を提供します。 これにより、 `+ requests `が信頼できる機関を知ることができます。 したがって、接続を可能な限り安全に保つために、頻繁に「 certifi +」を更新する必要があります。

パフォーマンス

特に実稼働アプリケーション環境で「リクエスト」を使用する場合、パフォーマンスへの影響を考慮することが重要です。 タイムアウト制御、セッション、再試行制限などの機能は、アプリケーションをスムーズに実行し続けるのに役立ちます。

タイムアウト

外部サービスにインラインリクエストを行う場合、システムは先に進む前に応答を待つ必要があります。 アプリケーションがその応答を待ちすぎると、サービスへのリクエストがバックアップされたり、ユーザーエクスペリエンスが低下したり、バックグラウンドジョブがハングしたりする可能性があります。

デフォルトでは、 `+ requests `は応答を無期限に待機するため、ほとんど常にタイムアウト期間を指定して、これらの事態が発生しないようにする必要があります。 リクエストのタイムアウトを設定するには、「 timeout 」パラメーターを使用します。 ` timeout +`は、タイムアウトになるまで応答を待つ秒数を表す整数または浮動小数点数です。

>>>

>>> requests.get('https://api.github.com', timeout=1)
<Response [200]>
>>> requests.get('https://api.github.com', timeout=3.05)
<Response [200]>

最初のリクエストでは、リクエストは1秒後にタイムアウトします。 2番目の要求では、要求は3.05秒後にタイムアウトします。

http://docs.python-requests.org/en/master/user/advanced/#timeouts [タプルを渡すこともできます]に、最初の要素が接続タイムアウト(クライアントはサーバーへの接続を確立します)、2番目は読み取りタイムアウト(クライアントが接続を確立してから応答を待つ時間)です:

>>>

>>> requests.get('https://api.github.com', timeout=(2, 5))
<Response [200]>

要求が2秒以内に接続を確立し、接続が確立されてから5秒以内にデータを受信すると、応答は以前と同じように返されます。 リクエストがタイムアウトした場合、関数は `+ Timeout +`例外を発生させます:

import requests
from requests.exceptions import Timeout

try:
    response = requests.get('https://api.github.com', timeout=1)
except Timeout:
    print('The request timed out')
else:
    print('The request did not time out')

プログラムは `+ Timeout +`例外をキャッチし、それに応じて応答できます。

セッションオブジェクト

これまで、 + get()+`や `+ post()+`などの高レベルの `+ requests + APIを扱ってきました。 これらの機能は、リクエストを行ったときに何が起こっているかを抽象化したものです。 接続をどのように管理するかなど、実装の詳細を隠すため、接続について心配する必要はありません。

これらの抽象化の下には、「+ Session 」というクラスがあります。 リクエストの作成方法を微調整したり、リクエストのパフォーマンスを改善する必要がある場合は、 ` Session +`インスタンスを直接使用する必要があります。

セッションは、リクエスト間でパラメータを保持するために使用されます。 たとえば、複数のリクエストで同じ認証を使用する場合、セッションを使用できます。

import requests
from getpass import getpass

# By using a context manager, you can ensure the resources used by
# the session will be released after use
with requests.Session() as session:
    session.auth = ('username', getpass())

    # Instead of requests.get(), you'll use session.get()
    response = session.get('https://api.github.com/user')

# You can inspect the response just like you did before
print(response.headers)
print(response.json())

`+ session +`でリクエストを行うたびに、認証クレデンシャルで初期化されると、クレデンシャルが保持されます。

セッションの主なパフォーマンスの最適化は、永続的な接続という形で行われます。 アプリが `+ Session +`を使用してサーバーに接続すると、その接続は接続プールに保持されます。 アプリが同じサーバーに再度接続する場合、新しい接続を確立するのではなく、プールからの接続を再利用します。

最大再試行

要求が失敗した場合、アプリケーションに同じ要求を再試行させることができます。 ただし、デフォルトでは `+ requests +`はこれを行いません。 この機能を適用するには、カスタムhttp://docs.python-requests.org/en/master/user/advanced/#transport-adapters [トランスポートアダプター]を実装する必要があります。

トランスポートアダプターを使用すると、やり取りするサービスごとに構成のセットを定義できます。 たとえば、 `+ https://api.github.com `へのすべてのリクエストを3回再試行してから、最終的に ` ConnectionError `を発生させたいとします。 トランスポートアダプターを構築し、 ` max_retries `パラメーターを設定し、既存の ` Session +`にマウントします。

import requests
from requests.adapters import HTTPAdapter
from requests.exceptions import ConnectionError

github_adapter = HTTPAdapter(max_retries=3)

session = requests.Session()

# Use `github_adapter` for all requests to endpoints that start with this URL
session.mount('https://api.github.com', github_adapter)

try:
    session.get('https://api.github.com')
except ConnectionError as ce:
    print(ce)

+ HTTPAdapter +、 `+ github_adapter `を ` session `にマウントすると、 ` session +`はhttps://api.github.comへの各リクエストの設定に従います。

タイムアウト、トランスポートアダプター、およびセッションは、コードの効率とアプリケーションの復元力を維持するためのものです。

結論

Pythonの強力な `+ requests +`ライブラリについて学ぶのに長い道のりを歩んできました。

次のことができるようになりました。

  • + GET ++ POST +、 `+ PUT +`などのさまざまなHTTPメソッドを使用してリクエストを作成する

  • ヘッダー、認証、クエリ文字列、メッセージ本文を変更してリクエストをカスタマイズします

  • サーバーに送信するデータと、サーバーから返送されるデータを検査します

  • SSL証明書の検証を使用する

  • + max_retries ++ timeout +、セッション、およびトランスポートアダプターを使用して、 `+ requests +`を効果的に使用する

「+ requests +」の使用方法を学習したため、Webサービスの幅広い世界を探索し、それらが提供する魅力的なデータを使用して素晴らしいアプリケーションを構築することができます。