Python 3でWeb APIを使用する方法

前書き

APIまたはアプリケーションプログラム**インターフェースにより、開発者は1つのアプリを別のアプリと統合できます。 プログラムの内部動作の一部を限定的な方法で公開します。

APIを使用して、他のプログラムから情報を取得したり、Webブラウザーで通常行うことを自動化することができます。 APIを使用して、他の方法ではできないことを実行できる場合があります。 驚くほど多くのWebプロパティが、Twitter、Facebook、GitHub、DigitalOceanなど、より馴染みのあるWebサイトまたはモバイルアプリとともにWebベースのAPIを提供しています。

Python 3でのコーディング方法でいくつかのチュートリアルを進めており、快適である場合Pythonの構文、構造、および組み込みのhttps://www.digitalocean.com/community/tutorials/how-to-define-functions-in-python-3[functions]を使用すると、利用するPythonプログラムを作成できます。お気に入りのAPIの。

このガイドでは、https://www.google.com/url?sa = t&rct = j&q =&esrc = s&source = web&cd = 1&cad = rja&uact = 8&ved = 0ahUKEwjttPKwlJbVAhVILyYKHSdOCDIQFggmMAA&url = https%3A%2FでPythonを使用する方法を学習します。 %2Fdevelopers.digitalocean.com%2F&usg = AFQjCNH6P3GhnE-YCtIHW0RfVz6-WOX—​g [DigitalOcean API]を使用して、DigitalOceanアカウントに関する情報を取得します。 次に、学んだことをhttps://developer.github.com/v3/[GitHubのAPI]に適用する方法を見ていきます。

完了したら、Web APIに共通の概念を理解し、他のサービスからAPIを試すために使用できるステップバイステップのプロセスと実際のコードサンプルが得られます。

前提条件

このガイドを始める前に、次のものが必要です。

ステップ1-APIに慣れる

新しいAPIを使用するための最初のステップは、ドキュメントを見つけて方位を把握することです。 DigitalOcean APIドキュメントは、https://developers.digitalocean.com/から始まります。 他のサービスのAPIを見つけるには、サイトの名前と「API」を検索します。すべてのサービスがフロントページでそれらを宣伝するわけではありません。

一部のサービスには_APIラッパー_があります。 APIラッパーは、選択したプログラミング言語でAPIを使いやすくするためにシステムにインストールするコードです。 このガイドでは、APIの内部動作の多くを隠し、多くの場合APIが実行できるすべてを公開しないため、ラッパーを使用しません。 ラッパーは、何かを迅速に完了させたい場合に最適ですが、API自体が何を行うことができるかをしっかりと理解することは、ラッパーが目的に合っているかどうかを判断するのに役立ちます。

まず、https://developers.digitalocean.com/documentation/v2/にあるDigitalOcean APIの紹介をご覧になり、リクエストの送信方法とレスポンスで期待されることに関する基本事項のみを理解してください。 この時点では、次の3つだけを学習しようとしています。

  1. リクエストはどのようなものですか? それらはすべてURLだけですか? より詳細なリクエストの場合、データはどのようにフォーマットされますか? 通常はhttps://www.digitalocean.com/community/tutorials/an-introduction-to-json[JSON]またはWebブラウザーが使用するクエリ文字列パラメーターですが、一部はXMLまたはカスタム形式を使用します。

  2. 応答はどのように見えますか? APIドキュメントには、リクエストとレスポンスのサンプルが表示されます。 JSON、XML、またはその他の種類の応答を取得しますか?

  3. 要求または応答ヘッダーには何が入りますか? 多くの場合、要求ヘッダーには認証トークンが含まれ、応答ヘッダーには、レート制限にどれだけ近いかなど、サービスの使用に関する現在の情報が提供されます。

DigitalOcean APIは、HTTP methods(_verbs_と呼ばれることもあります)を使用して、既存の情報の読み取り、新しい情報の作成、または何かの削除を試みているかどうかを示します。 ドキュメントのこの部分では、使用されるメソッドと目的を説明します。 一般に、GETリクエストはPOSTよりも簡単ですが、ここで作業を終える頃には、それほど大きな違いはありません。

APIドキュメントの次のセクションでは、サーバーがリクエストにどのように応答するかについて説明します。 一般に、リクエストは成功するか失敗します。 失敗した場合、原因はリクエストに問題があるか、サーバー上の問題です。 この情報はすべて、https://www.digitalocean.com/community/tutorials/how-to-troubleshoot-common-http-error-codes [HTTPステータスコード]を使用して伝達されます。HTTPステータスコードは、3桁の数字をカテゴリに分けたものです。

  • `+ 200 +`シリーズは「成功」を意味します-リクエストは有効であり、レスポンスはそれから論理的に続くものです。

  • `+ 400 `シリーズは「悪いリクエスト」を意味します-リクエストに何か問題があったので、サーバーはあなたが望むようにそれを処理しませんでした。 HTTP ` 400 +`レベルのエラーの一般的な原因は、フォーマットが不適切なリクエストと認証の問題です。

  • 「500」シリーズは「サーバーエラー」を意味します。リクエストは問題なかったかもしれませんが、サーバーは制御できない理由により、すぐに良い応答を返すことができませんでした。 これらはまれなはずですが、コードでそれらを処理できるように、可能性を認識する必要があります。

コードは、HTTPステータスコードを使用して何かを実行する前に、常にHTTPステータスコードをチェックする必要があります。 これを行わないと、不完全な情報でトラブルシューティングに時間を浪費することになります。

リクエストを送信する方法と、レスポンスで何を検索するかについての一般的なアイデアが得られたので、次は最初のリクエストを送信します。

ステップ2-Web APIから情報を取得する

DigitalOceanアカウントには、Web UIには表示されていない管理情報が含まれています。 APIを使用すると、馴染みのある情報をさまざまな方法で表示できます。 この別のビューを見るだけで、APIで何をしたいのかというアイデアを思い起こさせたり、知らないサービスやオプションを明らかにしたりすることがあります。

スクリプト用のプロジェクトを作成することから始めましょう。 `+ apis +`というプロジェクトの新しいディレクトリを作成します。

mkdir apis

次に、この新しいディレクトリに移動します。

cd apis

このプロジェクトの新しいvirtualenvを作成します。

python3 -m venv apis

virtualenvを起動します。

source apis/bin/activate

次に、http://docs.python-requests.org/en/master/ [requests]ライブラリをインストールします。これをスクリプトで使用して、スクリプトでHTTPリクエストを作成します。

pip install requests

環境を設定したら、 `+ do_get_account.py +`という新しいPythonファイルを作成し、テキストエディターで開きます。 JSONおよびHTTPリクエストを処理するには、https://www.digitalocean.com/community/tutorials/how-to-import-modules-in-python-3 [ライブラリのインポート]からこのプログラムを開始します。

do_get_account.py

import json
import requests

これらの `+ import +`ステートメントはPythonコードをロードするため、JSONデータ形式とHTTPプロトコルを使用できます。 これらのライブラリを使用しているのは、HTTPリクエストを送信する方法や、有効なJSONを解析および作成する方法の詳細に関心がないためです。これらを使用してこれらのタスクを実行したいだけです。 このチュートリアルのスクリプトはすべて、このように始まります。

次に、https://www.digitalocean.com/community/tutorials/how-to-use-variables-in-python-3 [variables]を設定して、すべてのリクエストで同じ情報を保持します。 これにより、何度も何度も入力する必要がなくなり、何か変更があった場合に更新を行うための単一の場所が得られます。 `+ import +`ステートメントの後に、これらの行をファイルに追加します。

do_get_account.py

...
api_token = ''
api_url_base = 'https://api.digitalocean.com/v2/'

`+ api_token `変数は、DigitalOcean APIトークンを保持する文字列です。 例の値を独自のトークンに置き換えます。 ` api_url_base +`変数は、DigitalOcean APIのすべてのURLから始まる文字列です。 コードの後半で必要に応じて追加します。

次に、APIドキュメントで説明されている方法でHTTPリクエストヘッダーを設定する必要があります。 これらの行をファイルに追加して、リクエストヘッダーを含むhttps://www.digitalocean.com/community/tutorials/understanding-dictionaries-in-python-3[dictionary]を設定します。

do_get_account.py

...
headers = {'Content-Type': 'application/json',
          'Authorization': 'Bearer {0}'.format(api_token)}

これにより、2つのヘッダーが同時に設定されます。 `+ Content-Type`ヘッダーは、リクエストの本文にJSON形式のデータが必要であることをサーバーに伝えます。 `+ Authorization `ヘッダーにはトークンを含める必要があるため、Pythonの文字列フォーマットロジックを使用して、文字列を作成するときに ` api_token +`変数を文字列に挿入します。 トークンをリテラル文字列としてここに入れることもできますが、トークンを分離することで、今後いくつかのことが容易になります。

  • トークンを置き換える必要がある場合は、別の変数を使用すると、どこでそれを行うかを簡単に確認できます。

  • コードを誰かと共有したい場合は、APIトークンを削除するのが簡単になり、友人がコードを置く場所を簡単に確認できます。

  • 自己文書化されています。 APIトークンが文字列リテラルとしてのみ使用される場合、コードを読んでいる人は自分が見ているものを理解できない可能性があります。

これらのセットアップの詳細が網羅されたので、実際にリクエストを送信します。 リクエストの作成と送信を開始したいかもしれませんが、もっと良い方法があります。 このロジックをリクエストの送信とレスポンスの読み取りを処理する関数に配置する場合、何をしているのかをもう少し明確に考える必要があります。 また、テストと再利用をより簡単にするコードになります。 それが私たちがやろうとしていることです。

この関数は、作成した変数を使用してリクエストを送信し、Python辞書でアカウント情報を返します。

この初期段階でロジックを明確にするため、詳細なエラー処理はまだ行いませんが、すぐに追加します。

アカウント情報を取得する関数を定義します。 関数の機能にちなんで名前を付けることは常に良い考えです。これはアカウント情報を取得するため、 `+ get_account_info +`と呼びます。

do_get_account.py

...
def :

    = '{0}account'.format(api_url_base)

    = requests.get(api_url, headers=headers)

   if response.status_code == 200:
       return json.loads(response.content.decode('utf-8'))
   else:
       return None

ヘッダーで使用したのと同様のPythonの文字列フォーマット方法を使用して、「+ api_url 」の値を作成します。 APIのベースURLを文字列「 account 」の前に追加して、アカウント情報を返すURL「 https://api.digitalocean.com/v2/account+」を取得します。

+ response +`変数は、Pythonの `+ requests + moduleによって作成されたオブジェクトを保持します。 この行は、スクリプトの開始時に定義したヘッダーを使用して作成したURLに要求を送信し、APIから応答を返します。

次に、レスポンスのHTTPステータスコードを確認します。

成功した応答である「200」の場合、「+ json」モジュールの「+ load」関数を使用して文字列をJSONとしてロードします。 ロードする文字列は、 + response`オブジェクトのコンテンツ、 + response.content`です。 `+ .decode( 'utf-8')`部分は、DigitalOcean APIからのすべての応答がそうであるように、このコンテンツがUTF-8文字セットを使用してエンコードされることをPythonに伝えます。 ` json +`モジュールはそれからオブジェクトを作成し、この関数の戻り値として使用します。

応答が_not_ `+ 200 `の場合、 ` None +`を返します。これは、この関数を呼び出すときに確認できるPythonの特別な値です。 この時点でエラーを無視していることに気付くでしょう。 これは、「成功」ロジックを明確に保つためです。 より包括的なエラーチェックを近日中に追加します。

次に、この関数を呼び出して、適切な応答が得られたことを確認し、APIが返した詳細を出力します。

do_get_account.py

...
= get_account_info()

if account_info is not None:
   print("Here's your info: ")
   for k, v in account_info['account'].items():
       print('{0}:{1}'.format(k, v))

else:
   print('[!] Request Failed')

`+ account_info = get_account_info()`は、 ` get_account_info()`の呼び出しから返されたものに ` account_info `変数を設定するため、特別な値 ` None +`になるか、コレクションになりますアカウントに関する情報。

`+ None `でない場合、すべてのPython辞書にある ` items()+`メソッドを使用して、各情報をそれぞれの行に出力します。

そうでない場合(つまり、 `+ account_info `が ` None +`の場合)、エラーメッセージを出力します。

ここでちょっと待ってみましょう。 二重否定を含むこの「+ if +」ステートメントは、最初は気まずく感じるかもしれませんが、一般的なPythonのイディオムです。 その長所は、成功時に実行されるコードをhttps://www.digitalocean.com/community/tutorials/how-to-write-conditional-statements-in-python-3-2[conditional]に非常に近く保つことにありますエラーケースを処理した後。

必要に応じて別の方法で行うこともできますが、実際にそのコードを自分で記述するのは良い練習になるかもしれません。 `+ if account_infoがNone:`ではない場合、 ` if account_infoがNone:+`で始まり、残りがどのように配置されるかを確認できます。

スクリプトを保存して試してください:

python do_get_account.py

出力は次のようになります。

OutputHere's your info:
droplet_limit:25
email:[email protected]
status:active
floating_ip_limit:3
email_verified:True
uuid:123e4567e89b12d3a456426655440000
status_message:

これで、APIからデータを取得する方法がわかりました。 次に、APIを使用してデータを変更する、もう少し興味深いものに進みます。

手順3-サーバー上の情報の変更

読み取り専用リクエストで練習したら、変更を開始します。 PythonとDigitalOcean APIを使用して、SSHキーをDigitalOceanアカウントに追加して、これを調べてみましょう。

まず、https://developers.digitalocean.com/documentation/v2/#ssh-keysで利用可能なSSHキーのAPIドキュメントをご覧ください。

APIを使用すると、アカウントの現在のSSHキーを一覧表示したり、新しいキーを追加したりできます。 SSHキーのリストを取得するリクエストは、アカウント情報を取得するリクエストとよく似ています。 ただし、応答は異なります。アカウントとは異なり、0、1、または多くのSSHキーを使用できます。

このスクリプト用に「+ do_ssh_keys.py +」という新しいファイルを作成し、最後のファイルとまったく同じように起動します。 JSONやHTTPプロトコルの詳細を気にする必要がないように、「」モジュールと「」モジュールをインポートします。 次に、DigitalOcean APIトークンを変数として追加し、辞書にリクエストヘッダーを設定します。

do_ssh_keys.py

import json
import requests


api_token = ''
api_url_base = 'https://api.digitalocean.com/v2/'
headers = {'Content-Type': 'application/json',
          'Authorization': 'Bearer {0}'.format(api_token)}

SSHキーを取得するために作成する関数は、アカウント情報を取得するために使用した関数と似ていますが、今回はエラーをより直接処理します。

最初に、API呼び出しを行い、応答を `+ response a`応答変数に保存します。 ただし、 `+ api_url `は前のスクリプトと同じではありません。今回は、 ` https:// api.digitalocean.com / v2 / account / keys +`を指す必要があります。

このコードをスクリプトに追加します。

do_ssh_keys.py

...
def get_ssh_keys():

   api_url = '{0}account/keys'.format(api_url_base)

   response = requests.get(api_url, headers=headers)

次に、応答のHTTPステータスコードを見て、エラー処理を追加します。 「200」の場合、以前と同じように、応答のコンテンツを辞書として返します。 それ以外の場合は、ステータスコードのタイプに関連する有用なエラーメッセージを出力して、 `+ None +`を返します。

次の行を `+ get_ssh_keys +`関数に追加します:

do_ssh_keys.py

...

   if response.status_code >= 500:
       print('[!] [{0}] Server Error'.format(response.status_code))
       return None
   elif response.status_code == 404:
       print('[!] [{0}] URL not found: [{1}]'.format(response.status_code,api_url))
       return None
   elif response.status_code == 401:
       print('[!] [{0}] Authentication Failed'.format(response.status_code))
       return None
   elif response.status_code == 400:
       print('[!] [{0}] Bad Request'.format(response.status_code))
       return None
   elif response.status_code >= 300:
       print('[!] [{0}] Unexpected Redirect'.format(response.status_code))
       return None
   elif response.status_code == 200:
       ssh_keys = json.loads(response.content.decode('utf-8'))
       return ssh_keys
   else:
       print('[?] Unexpected Error: [HTTP {0}]: Content: {1}'.format(response.status_code, response.content))
   return None

このコードは、応答内のHTTPステータスコードを調べることにより、6つの異なるエラー状態を処理します。

  • 「500」以上のコードは、サーバーの問題を示します。 これらはまれであり、リクエストの問題が原因ではないため、ステータスコードのみを出力します。

  • 「404」のコードは「見つかりません」という意味で、おそらくURLのタイプミスに起因します。 このエラーについては、ステータスコードとその原因となったURLを出力し、失敗の理由を確認できるようにします。

  • 「401」のコードは、認証が失敗したことを意味します。 この原因として最も可能性が高いのは、 `+ api_key +`の誤りまたは欠落です。

  • `+ 300 +`の範囲のコードはリダイレクトを示します。 DigitalOcean APIはリダイレクトを使用しないため、これは決して発生しませんが、エラーを処理している間は確認するのに問題はありません。 多くのバグは、プログラマーが決して発生してはならないと考えたことによって引き起こされます。

  • 「200」のコードは、リクエストが正常に処理されたことを意味します。 このため、何も印刷しません。 前のスクリプトで使用したのと同じ構文を使用して、sshキーをJSONオブジェクトとして返すだけです。

  • 応答コードがそれ以外の場合、ステータスコードを「予期しないエラー」として出力します。

これで、APIの呼び出しで発生する可能性のあるエラーを処理できます。 この時点で、エラーメッセージと `+ None +`オブジェクト、または成功と0個以上のSSHキーを含むJSONオブジェクトがあります。 次のステップは、それらを印刷することです。

do_ssh_keys.py

...

ssh_keys = get_ssh_keys()

if ssh_keys is not None:
   print('Here are your keys: ')
   for key, details in enumerate(ssh_keys['ssh_keys']):
       print('Key {}:'.format(key))
       for k, v in details.items():
           print('  {0}:{1}'.format(k, v))
else:
   print('[!] Request Failed')

レスポンスにはhttps://www.digitalocean.com/community/tutorials/understanding-lists-in-python-3[list](または配列)のSSHキーが含まれているため、リスト全体を反復処理するためにすべてのキーを参照してください。 これにはPythonの `+ enumerate`メソッドを使用します。 これは辞書で利用できる `+ items +`メソッドに似ていますが、代わりにリストで動作します。

https://www.digitalocean.com/community/tutorials/how-to-construct-for-loops-in-python-3#for-loops [`+ for `ループ]ではなく、 ` enumerate +`を使用しますなぜなら、私たちは与えられたキーに対してどれだけリストのどこにいるかを伝えたいからです。

各キーの情報は辞書として返されるため、前のスクリプトでアカウント情報辞書で使用したdetails.items():+ コードで同じ + for k、v 'を使用します。

このスクリプトを実行すると、アカウントに既に存在するSSHキーのリストが表示されます。

python get_ssh_keys.py

アカウントにすでにあるSSHキーの数に応じて、出力は次のようになります。

OutputHere are your keys:
Kcy 0:
 id:280518
 name:work
 fingerprint:96:f7:fb:9f:60:9c:9b:f9:a9:95:01:5c:5c:2c:d5:a0
 public_key:ssh-rsa AAAAB5NzaC1yc2cAAAADAQABAAABAQCwgr9Fzc/YTD/V2Ka5I52Rx4I+V2Ka5I52Rx4Ir5LKSCqkQ1Cub+... [email protected]
Kcy 1:
 id:290536
 name:home
 fingerprint:90:1c:0b:ac:fa:b0:25:7c:af:ab:c5:94:a5:91:72:54
 public_key:ssh-rsa AAAAB5NzaC1yc2cAAAABJQAAAQcAtTZPZmV96P9ziwyr5LKSCqkQ1CubarKfK5r7iNx0RNnlJcqRUqWqSt... [email protected]

アカウントのSSHキーをリストできるようになったので、ここでの最後のスクリプトは、リストに新しいキーを追加するスクリプトになります。

新しいSSHキーを追加する前に、キーを生成する必要があります。 このステップのより完全な処理については、チュートリアルhttps://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys—​2[SSHキーのセットアップ方法]をご覧ください。 。

ただし、この目的のためには、単純なキーが必要です。 このコマンドを実行して、Linux、BSD、またはMacOSで新しいコマンドを生成します。 必要に応じて、既存のドロップレットでこれを実行できます。

ssh-keygen -t rsa

プロンプトが表示されたら、ファイルを入力してキーを保存し、パスフレーズを提供しません。

OutputGenerating public/private rsa key pair.
Enter file in which to save the key (/home/sammy/.ssh/id_rsa):
Created directory '/home/sammy/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/sammy/.ssh/sammy.
Your public key has been saved in /home/sammy/.ssh/sammy.pub.
...

公開鍵ファイルはスクリプトに必要になるため、保存場所をメモしてください。

新しいPythonスクリプトを開始し、 `+ add_ssh_key.py +`を呼び出して、他のスクリプトと同様に開始します。

add_ssh_key.py

import json
import requests


api_token = ''
api_url_base = 'https://api.digitalocean.com/v2/'
headers = {'Content-Type': 'application/json',
          'Authorization': 'Bearer {0}'.format(api_token)}

関数を使用してリクエストを行いますが、これは少し異なります。

2つの引数を受け入れる「+ add_ssh_key 」という関数を作成します。新しいSSHキーに使用する名前と、ローカルシステム上のキー自体のファイル名です。 この関数は、https://www.digitalocean.com/community/tutorials/how-to-handle-plain-text-files-in-python-3 [ファイルを読む]、HTTP ` POST `リクエストを行い、 ` GET +`の代わりに:

add_ssh_key.py

...

def add_ssh_key(name, filename):

   api_url = '{0}account/keys'.format(api_url_base)

   with open(filename, 'r') as f:
       ssh_key = f.readline()

   ssh_key = {'name': name, 'public_key': ssh_key}

   response = requests.post(api_url, headers=headers, json=ssh_key)

行の `+ with open(filename、 'r')as f:`はファイルを読み取り専用モードで開き、それに続く行はファイルから最初の(そして唯一の)行を読み取り、それを ` ssh_key + `変数。

次に、APIが期待する名前と値を使用して、 `+ ssh_key +`というPython辞書を作成します。

ただし、リクエストを送信すると、もう少し新しいものがあります。 これは「+ GET 」ではなく「 POST 」であり、JSONとしてエンコードされた「 POST 」リクエストの本文で「 ssh_key 」を送信する必要があります。 ` requests `モジュールは詳細を処理します。 ` requests.post `は、 ` POST `メソッドを使用するように指示し、 ` json = ssh_key `を含めると、JSONとしてエンコードされたリクエストの本文で ` ssh_key +`変数を送信するように指示します。

APIによると、応答は成功すると「200」ではなくHTTP「201」になり、応答の本文には追加したばかりのキーの詳細が含まれます。

次のエラー処理コードを `+ add_ssh_key `関数に追加します。 前のスクリプトと似ていますが、今回は成功のために「+200」ではなく「201」のコードを探す必要があります。

add_ssh_key.py

...
   if response.status_code >= 500:
       print('[!] [{0}] Server Error'.format(response.status_code))
       return None
   elif response.status_code == 404:
       print('[!] [{0}] URL not found: [{1}]'.format(response.status_code,api_url))
       return None
   elif response.status_code == 401:
       print('[!] [{0}] Authentication Failed'.format(response.status_code))
       return None
   elif response.status_code >= 400:
       print('[!] [{0}] Bad Request'.format(response.status_code))
       print(ssh_key )
       print(response.content )
       return None
   elif response.status_code >= 300:
       print('[!] [{0}] Unexpected redirect.'.format(response.status_code))
       return None
   elif response.status_code == 201:
       added_key = json.loads(response.content)
       return added_key
   else:
       print('[?] Unexpected Error: [HTTP {0}]: Content: {1}'.format(response.status_code, response.content))
       return None

この関数は、前の関数と同様に、「+ None +」または応答コンテンツのいずれかを返すため、前と同じアプローチを使用して結果を確認します。

次に、関数を呼び出して結果を処理します。 2番目の引数として、新しく作成したSSHキーへのパスを渡します。

add_ssh_key.py

...
add_response = add_ssh_key('tutorial_key', '')

if add_response is not None:
   print('Your key was added: ' )
   for k, v in add_response.items():
       print('  {0}:{1}'.format(k, v))
else:
   print('[!] Request Failed')

このスクリプトを実行すると、新しいキーが追加されたことを知らせる応答が返されます。

python add_ssh_key.py

出力は次のようになります。

OutputYour key was added:
 ssh_key:{'id': 9458326, 'name': 'tutorial_key', 'fingerprint': '64:76:37:77:c8:c7:26:05:f5:7b:6b:e1:bb:d6:80:da', 'public_key': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCUtY9aizEcVJ65/O5CE6tY8Xodrkkdh9BB0GwEUE7eDKtTh4NAxVjXc8XdzCLKtdMwfSg9xwxSi3axsVWYWBUhiws0YRxxMNTHCBDsLFTJgCFC0JCmSLB5ZEnKl+Wijbqnu2r8k2NoXW5GUxNVwhYztXZkkzEMNT78TgWBjPu2Tp1qKREqLuwOsMIKt4bqozL/1tu6oociNMdLOGUqXNrXCsOIvTylt6ROF3a5UnVPXhgz0qGbQrSHvCEfuKGZ1kw8PtWgeIe7VIHbS2zTuSDCmyj1Nw1yOTHSAqZLpm6gnDo0Lo9OEA7BSFr9W/VURmTVsfE1CNGSb6c6SPx0NpoN [email protected]'}

「200」ではなくHTTP「201」を探すために「成功」​​条件を変更するのを忘れた場合、エラーが報告されますが、キーは追加されたままになります。 エラー処理では、ステータスコードが「201」であることが通知されます。 成功を示す `+ 200 +`シリーズのメンバーとしてそれを認識する必要があります。 これは、基本的なエラー処理がトラブルシューティングを簡単にする方法の例です。

このスクリプトでキーを正常に追加したら、もう一度実行して、既に存在するキーを追加しようとしたときに何が起こるかを確認します。

APIはHTTP `+ 422 +`応答を送り返し、スクリプトは「アカウントで既にSSHキーが使用されています」というメッセージに変換します。

Output[!] [422] Bad Request
{'name': 'tutorial_key', 'public_key': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCUtY9aizEcVJ65/O5CE6tY8Xodrkkdh9BB0GwEUE7eDKtTh4NAxVjXc8XdzCLKtdMwfSg9xwxSi3axsVWYWBUhiws0YRxxMNTHCBDsLFTJgCFC0JCmSLB5ZEnKl+Wijbqnu2r8k2NoXW5GUxNVwhYztXZkkzEMNT78TgWBjPu2Tp1qKREqLuwOsMIKt4bqozL/1tu6oociNMdLOGUqXNrXCsOIvTylt6ROF3a5UnVPXhgz0qGbQrSHvCEfuKGZ1kw8PtWgeIe7VIHbS2zTuSDCmyj1Nw1yOTHSAqZLpm6gnDo0Lo9OEA7BSFr9W/VURmTVsfE1CNGSb6c6SPx0NpoN [email protected]'}
b'{"id":"unprocessable_entity","message":"SSH Key is already in use on your account"}'
[!] Request Failed

ここで、 `+ get_ssh_keys.py +`スクリプトを再度実行すると、リストに新しく追加されたキーが表示されます。

わずかな変更を加えるだけで、これら2つのスクリプトを使用して、必要なときにいつでも新しいSSHキーをDigitalOceanアカウントに追加できます。 このAPIの関連関数を使用すると、一意のキーIDまたはフィンガープリントを使用して、特定のキーの名前を変更または削除できます。

別のAPIを見て、今学んだスキルがどのように翻訳されるかを見てみましょう。

ステップ4-別のAPIを使用する

GitHubにはAPIもあります。 DigitalOcean APIの使用について学んだことはすべて、GitHub APIの使用に直接適用できます。

DigitalOceanで行ったのと同じ方法でGitHub APIを理解してください。 API documentationを検索し、*概要*セクションをざっと読んでください。 GitHub APIとDigitalOcean APIにはいくつかの類似点があることがすぐにわかります。

まず、すべてのAPI URLに共通のルートである「+ https://api.github.com/+」があることに気付くでしょう。 コード内の変数としてそれを使用して、エラーの可能性を合理化し削減する方法を知っています。

GitHubのAPIは、DigitalOceanと同じようにJSONをリクエストとレスポンスの形式として使用しているため、これらのリクエストを作成してレスポンスを処理する方法を知っています。

応答には、DigitalOceanとほぼ同じ名前とまったく同じ値を使用して、HTTP応答ヘッダーにレート制限に関する情報が含まれます。

GitHubは認証にOAuthを使用し、リクエストヘッダーでトークンを送信できます。 このトークンの詳細は少し異なりますが、使用方法はDigitalOceanのAPIで行った方法と同じです。

いくつかの違いもあります。 GitHubでは、使用するAPIのバージョンを示すリクエストヘッダーの使用を推奨しています。 Pythonでリクエストにヘッダーを追加する方法を知っています。

GitHubでは、リクエストで一意の `+ User-Agent`文字列を使用することも求めているため、コードが問題を引き起こしている場合は、より簡単に見つけることができます。 これもヘッダーで処理します。

GitHub APIは同じHTTPリクエストメソッドを使用しますが、特定の操作に対して `+ PATCH `という新しいメソッドも使用します。 GitHub APIは、情報を読み取るために「 GET 」、新しいアイテムを追加するために「 POST 」、および既存のアイテムを変更するために「 PATCH 」を使用します。 この ` PATCH +`リクエストは、APIドキュメントで注目したいものです。

すべてのGitHub API呼び出しが認証を必要とするわけではありません。 たとえば、アクセストークンを必要とせずに、ユーザーのリポジトリのリストを取得できます。 そのリクエストを行い、結果を表示するスクリプトを作成しましょう。

このスクリプトのエラー処理を簡素化し、1つのステートメントのみを使用して、考えられるすべてのエラーを処理します。 さまざまな種類のエラーを個別に処理するためにコードが常に必要なわけではありませんが、エラー状態で何かをするのは良いことです。

エディターで `+ github_list_repos.py +`という名前の新しいファイルを作成し、次のコンテンツを追加します。

github_list_repos.py

import json
import requests


api_url_base = 'https://api.github.com/'
headers = {'Content-Type': 'application/json',
          'User-Agent': 'Python Student',
          'Accept': 'application/vnd.github.v3+json'}

インポートは、これまで使用してきたものと同じです。 `+ api_url_base +`は、すべてのGitHub APIが始まる場所です。

ヘッダーには、GitHubが概要で言及している2つのオプションのヘッダーと、リクエストでJSON形式のデータを送信しているというヘッダーが含まれています。

これは小さなスクリプトですが、ロジックをモジュール化してリクエストを行うためのロジックをカプセル化するために、関数を定義します。 多くの場合、小さなスクリプトはより大きなスクリプトに成長するため、これについて熱心に取り組むと役に立ちます。 引数としてユーザー名を受け入れる `+ get_repos +`という関数を追加します。

github_list_repos.py

...
def get_repos(username):

   api_url = '{}orgs/{}/repos'.format(api_url_base, username)

   response = requests.get(api_url, headers=headers)

   if response.status_code == 200:
       return (response.content)
   else:
       print('[!] HTTP {0} calling [{1}]'.format(response.status_code, api_url))
       return None

関数内で、「+ api_url_base +」、関心のあるユーザーの名前、およびGitHubにリポジトリリストが必要であることを伝えるURLの静的部分からURLを構築します。 次に、応答のHTTPステータスコードをチェックして、それが「+200 +」(成功)であることを確認します。 成功した場合、応答コンテンツを返します。 そうでない場合は、実際のステータスコードと作成したURLを出力します。これにより、どこが間違っているのかがわかります。

次に、関数を呼び出して、使用するGitHubユーザー名を渡します。 この例では、「+ octokit +」を使用します。 次に、結果を画面に印刷します。

github_list_repos.py

...
repo_list = get_repos('')

if repo_list is not None:
   print(repo_list)
else:
   print('No Repo List Found')

ファイルを保存し、スクリプトを実行して、指定したユーザーのリポジトリを表示します。

python github_list_repos.py

この例では応答をJSONとして解析しておらず、結果を特定のキーにフィルター処理していないため、出力には多くのデータが表示されます。 他のスクリプトで学んだことを使ってそれを行います。 取得した結果を見て、リポジトリ名を印刷できるかどうかを確認します。

これらのGitHub APIの優れた点は、認証が不要なリクエストにWebブラウザーで直接アクセスできることです。これにより、スクリプトで表示されているものとレスポンスを比較できます。 ブラウザーでhttps://api.github.com/orgs/octokit/reposにアクセスして、応答を確認してください。

これで、GitHub APIを使用して独自の目標をサポートするために、ドキュメントを読み、より具体的なリクエストを送信するために必要なコードを記述する方法を理解できました。

このチュートリアルのすべての例の完成したコードは、https://github.com/do-community/python3_web_api_tutorial [GitHubのこのリポジトリ]にあります。

結論

このチュートリアルでは、スタイルがわずかに異なる2つの異なるサービスでWeb APIを使用する方法を学びました。 デバッグを容易にし、スクリプトをより堅牢にするために、エラー処理コードを含めることの重要性を見てきました。 Pythonモジュールの `+ requests `と ` json +`を使用してこれらのテクノロジーの詳細から隔離し、作業を完了させ、スクリプトをよりモジュール化するためにリクエストとレスポンスの処理を関数にカプセル化しました。

さらに、新しいWeb APIを学習する際に従うべき反復可能なプロセスがあります。

  1. APIを操作する方法の基本を理解するために、ドキュメントを見つけて概要を読んでください。

  2. 必要に応じて認証トークンを取得し、基本的なエラー処理を備えたモジュラースクリプトを記述して、単純なリクエストを送信し、エラーに応答し、応答を処理します。

  3. サービスから必要な情報を取得するリクエストを作成します。

ここで、この新たに得られた知識を固め、使用する別のAPI、またはここで使用したAPIの別の機能を見つけます。 独自のプロジェクトは、ここで学んだことを固めるのに役立ちます。

前の投稿:CentOS 7でLet’s Encryptを使用してApacheを保護する方法
次の投稿:Iptables Essentials:一般的なファイアウォールルールとコマンド