序章

API、またはAアプリケーションPログラムIインターフェースを使用すると、開発者は1つのアプリを別のアプリと統合できます。 それらは、限られた方法でプログラムの内部動作の一部を公開します。

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

Python 3 でのコーディング方法に関するチュートリアルをいくつか試し、Pythonの構文、構造、およびいくつかの組み込み関数に慣れている場合は、次のことができます。お気に入りのAPIを利用するPythonプログラムを作成します。

このガイドでは、Pythonを DigitalOcean API で使用して、DigitalOceanアカウントに関する情報を取得する方法を学習します。 次に、学習した内容を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/にあるDigitalOceanAPIの概要を見て、リクエストの送信方法とレスポンスで何を期待するかについての基本のみを理解してください。 。 この時点で、あなたは3つのことだけを学ぼうとしています。

  1. リクエストはどのように見えますか? それらはすべて単なるURLですか? より詳細なリクエストについては、データはどのようにフォーマットされていますか? これは通常、 JSON またはWebブラウザーが使用するようなクエリ文字列パラメーターですが、XMLまたはカスタム形式を使用するものもあります。
  2. 応答はどのように見えますか? APIドキュメントには、サンプルのリクエストとレスポンスが表示されます。 JSON、XML、またはその他の種類の応答を取得しますか?
  3. リクエストヘッダーまたはレスポンスヘッダーには何が入りますか? 多くの場合、リクエストヘッダーには認証トークンが含まれ、レスポンスヘッダーには、レート制限にどれだけ近づいているかなど、サービスの使用に関する現在の情報が提供されます。

DigitalOcean APIは、HTTP メソッド動詞と呼ばれることもあります)を使用して、既存の情報を読み取ろうとしているのか、新しい情報を作成しようとしているのか、何かを削除しようとしているのかを示します。 ドキュメントのこの部分では、使用される方法と目的について説明します。 一般に、GETリクエストはPOSTよりも単純ですが、ここで完了するまでに、大きな違いに気付くことはありません。

APIドキュメントの次のセクションでは、サーバーがリクエストにどのように応答するかについて説明します。 一般に、リクエストは成功するか失敗します。 失敗した場合、原因はリクエストに問題があるか、サーバーに問題があります。 この情報はすべて、 HTTPステータスコードを使用して伝達されます。これは、カテゴリに分類された3桁の数字です。

  • 200シリーズは「成功」を意味します—リクエストは有効であり、応答は論理的にそれに続くものです。
  • 400シリーズは「不正なリクエスト」を意味します—リクエストに問題があったため、サーバーはリクエストを希望どおりに処理しませんでした。 HTTP 400レベルのエラーの一般的な原因は、形式が正しくない要求と認証の問題です。
  • 500シリーズは、「サーバーエラー」を意味します。リクエストは問題ない可能性がありますが、サーバーは、制御できない理由により、現在、適切な応答を返すことができませんでした。 これらはまれなはずですが、コードで処理できるように、その可能性を認識する必要があります。

コードで何かをしようとする前に、コードは常にHTTPステータスコードで応答を確認する必要があります。 これを行わないと、不完全な情報でトラブルシューティングに時間を浪費することになります。

リクエストを送信する方法と、レスポンスで何を探すべきかについての一般的な考え方がわかったので、次はその最初のリクエストを送信します。

ステップ2—WebAPIから情報を取得する

DigitalOceanアカウントには、WebUIには表示されない可能性のあるいくつかの管理情報が含まれています。 APIを使用すると、使い慣れた情報の別のビューを得ることができます。 この代替ビューを見るだけで、APIで何をしたいかについてのアイデアが生まれたり、知らなかったサービスやオプションが明らかになったりすることがあります。

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

  1. mkdir apis

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

  1. cd apis

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

  1. python3 -m venv apis

virtualenvをアクティブにします。

  1. source apis/bin/activate

次に、 requests ライブラリをインストールします。これをスクリプトで使用して、スクリプトでHTTPリクエストを作成します。

  1. pip install requests

環境を構成した状態で、do_get_account.pyという新しいPythonファイルを作成し、テキストエディターで開きます。 JSONおよびHTTPリクエストを処理するためにライブラリをインポートして、このプログラムを開始します。

do_get_account.py
import json
import requests

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

次に、すべてのリクエストで同じ情報を保持するために、いくつかの変数を設定します。 これにより、何度も入力する必要がなくなり、何かが変更された場合に更新を行うための単一の場所が提供されます。 importステートメントの後に、これらの行をファイルに追加します。

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

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

次に、APIドキュメントで説明されている方法でHTTPリクエストヘッダーを設定する必要があります。 次の行をファイルに追加して、リクエストヘッダーを含む辞書を設定します。

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 get_account_info():
  
    api_url = '{0}account'.format(api_url_base)

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

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

response変数は、Python requestsモジュールによって作成されたオブジェクトを保持します。 この行は、スクリプトの開始時に定義したヘッダーを使用して作成したURLにリクエストを送信し、APIからのレスポンスを返します。

次に、応答のHTTPステータスコードを確認します。

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

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

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

do_get_account.py
...
account_info = 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()は、account_info変数を、get_account_info()の呼び出しから戻ってきたものに設定するため、特別な値Noneになるか、コレクションになります。アカウントに関する情報の。

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

それ以外の場合(つまり、account_infoNoneの場合)、エラーメッセージが出力されます。

ここで少し一時停止しましょう。 このifステートメントに二重否定が含まれていると、最初は扱いにくいと感じるかもしれませんが、これは一般的なPythonイディオムです。 その長所は、エラーケースを処理した後ではなく、成功時に実行されるコードを条件付きに非常に近い状態に保つことです。

必要に応じて別の方法で行うこともできます。実際にそのコードを自分で作成することをお勧めします。 if account_info is not None:の代わりに、if account_info is None:から始めて、残りがどのように配置されるかを確認できます。

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

  1. python do_get_account.py

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

Output
Here'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とDigitalOceanAPIを使用してSSHキーをDigitalOceanアカウントに追加することにより、これを調べてみましょう。

まず、https://developers.digitalocean.com/documentation/v2/#ssh-keysで入手できるSSHキーのAPIドキュメントを確認してください。

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

このスクリプト用にdo_ssh_keys.pyという名前の新しいファイルを作成し、最後のファイルとまったく同じように開始します。 jsonおよびrequestsモジュールをインポートして、JSONまたはHTTPプロトコルの詳細について心配する必要がないようにします。 次に、DigitalOcean APIトークンを変数として追加し、辞書にリクエストヘッダーを設定します。

do_ssh_keys.py
import json
import requests


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

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

まず、API呼び出しを行い、応答をresponse応答変数に格納します。 ただし、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')

応答にはSSHキーのlist(または配列)が含まれているため、すべてのキーを表示するためにリスト全体を反復処理する必要があります。 これには、Pythonのenumerateメソッドを使用します。 これは、辞書で使用できるitemsメソッドに似ていますが、代わりにリストで機能します。

forループだけでなく、enumerateを使用します。これは、特定のキーについて、リストのどこまで進んでいるかを確認できるようにするためです。

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

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

  1. python get_ssh_keys.py

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

Output
Here 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+... sammy@work 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... sammy@home

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

新しいSSHキーを追加する前に、SSHキーを生成する必要があります。 この手順の詳細については、チュートリアルSSHキーの設定方法を参照してください。

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

  1. ssh-keygen -t rsa

プロンプトが表示されたら、ファイルを入力してキーを保存し、パスフレーズを入力しないでください。

Output
Generating public/private rsa key pair. Enter file in which to save the key (/home/sammy/.ssh/id_rsa): /home/sammy/.ssh/sammy 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 = 'your_api_token'
api_url_base = 'https://api.digitalocean.com/v2/'
headers = {'Content-Type': 'application/json',
           'Authorization': 'Bearer {0}'.format(api_token)}

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

add_ssh_keyという関数を作成します。この関数は、新しいSSHキーに使用する名前と、ローカルシステム上のキー自体のファイル名の2つの引数を受け入れます。 この関数はファイルを読み取り、GETの代わりにHTTPPOSTリクエストを作成します。

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ではなくHTTP201になり、応答の本文には、追加したキーの詳細が含まれます。

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または応答コンテンツのいずれかを返すため、前と同じアプローチを使用して結果を確認します。

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

add_ssh_key.py
...
add_response = add_ssh_key('tutorial_key', '/home/sammy/.ssh/sammy.pub')

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')

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

  1. python add_ssh_key.py

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

Output
Your 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 sammy@tutorial-test'}

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

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

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

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

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

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

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

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

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

DigitalOceanで行ったのと同じ方法で、GitHubAPIに精通します。 APIドキュメントを検索し、概要セクションをざっと読みます。 GitHubAPIとDigitalOceanAPIがいくつかの類似点を共有していることがすぐにわかります。

まず、すべてのAPIURLに共通のルート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ドキュメントで注目したい種類のものです。

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

このスクリプトではエラー処理を簡略化し、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は、すべてのGitHubAPIが始まる場所です。

ヘッダーには、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('octokit')

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

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

  1. python github_list_repos.py

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

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

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

このチュートリアルのすべての例の完成したコードは、GitHubこのリポジトリにあります。

結論

このチュートリアルでは、スタイルがわずかに異なる2つの異なるサービスにWebAPIを使用する方法を学習しました。 デバッグを容易にし、スクリプトをより堅牢にするために、エラー処理コードを含めることの重要性を理解しました。 Pythonモジュールrequestsjsonを使用して、これらのテクノロジーの詳細からあなたを隔離し、作業を完了し、要求と応答の処理を関数にカプセル化して、スクリプトをさらに作成しました。基本単位。

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

  1. ドキュメントを見つけて概要を読み、APIの操作方法の基本を理解してください。
  2. 必要に応じて認証トークンを取得し、基本的なエラー処理を備えたモジュラースクリプトを記述して、単純な要求を送信し、エラーに応答し、応答を処理します。
  3. サービスから必要な情報を取得するリクエストを作成します。

ここで、この新しく得られた知識を強化し、使用する別のAPI、またはここで使用したAPIの1つの別の機能を見つけます。 あなた自身のプロジェクトはあなたがここで学んだことを固めるのを助けるでしょう。