このチュートリアルでは、PythonのcURLライブラリへのインターフェースであるPycURLの使い方を学びます。
cURLは、サーバーとの間でデータを転送したり、さまざまな種類のデータ要求を行うために使用されるツールです。
PycURLはREST APIをテストしたり、ファイルをダウンロードしたりするのに最適です。
開発者の中にはAPIのテストにPostmanを使うことを好む人もいますが、PycURLはFILE、FTPS、HTTPS、IMAP、POP3、SMTP、SCP、SMBなどの複数のプロトコルをサポートしているので、APIのテストに適した別のオプションと言えます。
さらに、PycURLは、多くの同時接続、高速接続、および信頼性の高い接続が必要な場合に便利です。
前述のとおり、PycURLはPythonのlibcURLライブラリへのインタフェースであり、したがってPycURLはlibcURLのすべての機能を継承しています。
PycURLは非常に高速で(HTTPリクエスト用のPythonライブラリであるRequestsよりもはるかに高速であることが知られています)、マルチプロトコルをサポートしており、ネットワーク操作をサポートするためのソケットも含まれています。
前提条件
このチュートリアルを進める前に、いくつかの前提条件があることに注意してください。
Pythonの構文の基本的な理解、および/または、他の言語での少なくとも初級レベルのプログラミング経験が必要です。
さらに、プロトコルとその型、クライアントサーバーモードの通信のような一般的なネットワークの概念についてよく理解している必要があります。
これらの概念に精通していることは、PycURLライブラリを理解するために必要不可欠です。
インストール
PycURLのインストール手順は、すべてのオペレーティングシステムでかなりシンプルで簡単です。
PycURLを使用するためには、システムにlibcURLをインストールする必要があるだけです。
Mac/Linux OS
Mac OSとLinuxの場合、PycURLのインストールは依存関係がなく、libcURLがデフォルトでインストールされているため、最も簡単な方法です。
ターミナルで以下のコマンドを実行するだけで、インストールが完了します。
pipによるインストール
$ pip install pycurl
Easy_install によるインストール
$ easy_install pycurl
Windows OS
しかし、Windowsの場合、PyCURLをプログラムで使用する前にインストールする必要がある依存関係がいくつかあります。
Pythonの公式ディストリビューション(公式サイト https://www.python.org からPythonのバージョンをダウンロードしたもの)とpipを使用している場合は、コマンドラインで以下のコマンドを実行するだけでインストールは完了します。
$ pip install pycurl
pipを使用していない場合は、PycURL WindowsでEXEとMSIのインストーラが利用できます。
他のアプリケーションと同様に、そこから直接ダウンロードし、インストールすることができます。
基本的なコード例
このセクションでは、インターフェイスのさまざまな機能を示すPycURLのコーディング例をいくつか取り上げます。
導入のセクションで述べたように、PycURLは多くのプロトコルをサポートし、多くの洗練された機能を備えています。
ただし、この例ではHTTPプロトコルを使用して、HTTPの最も一般的に使用されるメソッドを使用してREST APIをテストする予定です。
GET、POST、PUT、DELETE、およびその他のいくつかの例もあります。
Python 3でそれらを宣言するための構文を書き、またそれらが何を行うかを説明します。
では、始めましょう
例 1:HTTP GET 要求を送信する
PycURLの簡単なネットワーク操作は、指定されたサーバーからそのURLを使用して情報を取得することです。
これは、ネットワークリソースを「取得」するために使用されるため、GETリクエストと呼ばれます。
PycURLを使用して単純なGETリクエストを実行するには、BytesIOモジュールをインポートして、そのオブジェクトを作成します。
CURLオブジェクトは、URL上でデータやファイルを転送するために作成されます。
目的の URL は setopt()
関数を使用して設定します。
この関数は setopt(option, value)
として使用されます。
optionパラメータは、
URLや
WRITEDATAなど、どのオプションを設定するかを指定し、
value` パラメータはその特定のオプションに与えられた値を指定する。
設定された URL から取得されたデータは、BytesIO オブジェクトにバイトの形式で書き込まれます。
そのバイトは getvalue()
関数を使って BytesIO オブジェクトから読み込まれ、その後デコードされてコンソールに HTML が出力されます。
以下は、その方法の例です。
import pycurl
from io import BytesIO
b_obj = BytesIO()
crl = pycurl.Curl()
# Set URL value
crl.setopt(crl.URL, 'https://wiki.python.org/moin/BeginnersGuide')
# Write bytes that are utf-8 encoded
crl.setopt(crl.WRITEDATA, b_obj)
# Perform a file transfer
crl.perform()
# End curl session
crl.close()
# Get the content stored in the BytesIO object (in byte characters)
get_body = b_obj.getvalue()
# Decode the bytes stored in get_body to HTML and print the result
print('Output of GET request:
%s' % get_body.decode('utf8'))
出力
Output of GET request:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"
<html
<head
<meta content="IE=Edge" http-equiv="X-UA-Compatible"/
<meta content="width=device-width, initial-scale=1" name="viewport"/
<meta content="text/html; charset = utf-8" http-equiv="Content-Type"/
<meta content="index,nofollow" name="robots"/
<titleBeginnersGuide - Python Wiki</title
<script src="/wiki/common/js/common.js" type="text/javascript"</script
<script type="text/javascript"
<!--
var search_hint = "Search";
//--
</script
.
.
.
例2:GETレスポンスヘッダを調べる
PycURLの助けを借りて、Webサイトのレスポンスヘッダを取得することもできます。
レスポンスヘッダを調べる理由はいくつかありますが、たとえば、レスポンスとともに送信されたエンコードが何であるか、またそれがサーバーから提供されたエンコードに従っているかどうかを調べることができます。
この例では、レスポンスヘッダを調べて、さまざまな属性名とそれに対応する値を確認します。
レスポンスヘッダを調べるには、まずそれを抽出する必要があります。
そのためには HEADERFUNCTION
オプションを使用し、自分で定義した関数 (この例では display_header()
) でそれを表示させます。
HEADERFUNCTIONはレスポンスヘッダを
display_header()` 関数に送り、そこで適切にフォーマットされます。
レスポンスヘッダは指定された標準に従ってデコードされ、対応する名前と値に分割されます。
名前と値の間の空白は取り除かれ、小文字に変換される。
レスポンスヘッダはBytesIOオブジェクトに書き込まれ、リクエスタに転送され、最終的に適切なフォーマットで表示されます。
from io import BytesIO
import pycurl
headers = {}
def display_header(header_line):
header_line = header_line.decode('iso-8859-1')
# Ignore all lines without a colon
if ':' not in header_line:
return
# Break the header line into header name and value
h_name, h_value = header_line.split(':', 1)
# Remove whitespace that may be present
h_name = h_name.strip()
h_value = h_value.strip()
h_name = h_name.lower() # Convert header names to lowercase
headers[h_name] = h_value # Header name and value.
def main():
print('**Using PycURL to get Twitter Headers**')
b_obj = BytesIO()
crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://twitter.com')
crl.setopt(crl.HEADERFUNCTION, display_header)
crl.setopt(crl.WRITEDATA, b_obj)
crl.perform()
print('Header values:-')
print(headers)
print('-' * 20)
main()
出力する。
**Using PycURL to get Twitter Headers**
Header values:-
{'cache-control': 'no-cache, no-store, must-revalidate, pre-check=0, post-check=0', 'content-length': '303055', 'content-type': 'text/html;charset=utf-8', 'date': 'Wed, 23 Oct 2019 13:54:11 GMT', 'expires': 'Tue, 31 Mar 1981 05:00:00 GMT', 'last-modified': 'Wed, 23 Oct 2019 13:54:11 GMT', 'pragma': 'no-cache', 'server': 'tsa_a', 'set-cookie': 'ct0=ec07cd52736f70d5f481369c1d762d56; Max-Age=21600; Expires=Wed, 23 Oct 2019 19:54:11 GMT; Path=/; Domain=.twitter.com; Secure', 'status': '200 OK', 'strict-transport-security': 'max-age=631138519', 'x-connection-hash': 'ae7a9e8961269f00e5bde67a209e515f', 'x-content-type-options': 'nosniff', 'x-frame-options': 'DENY', 'x-response-time': '26', 'x-transaction': '00fc9f4a008dc512', 'x-twitter-response-tags': 'BouncerCompliant', 'x-ua-compatible': 'IE=edge,chrome=1', 'x-xss-protection': '0'}
--------------------
同じ名前のヘッダーが複数ある場合、最後のヘッダーの値だけが保存されます。
複数の値を持つヘッダーにすべての値を格納するには、次のようなコードを使用します。
if h_name in headers:
if isinstance(headers[h_name], list):
headers[name].append(h_value)
else:
headers[h_name] = [headers[h_name], h_value]
else:
headers[h_name] = h_value
例3:HTTP POSTでフォームデータを送信する
POSTリクエストとは、HTTPリクエストのボディにデータを囲んでWebサーバーに送信するものです。
ファイルのアップロードやフォームの送信は、基本的にPOSTリクエストを指定のサーバーに送信していることになります。
POSTリクエストは、PycURLを使用して、まず setopt
関数でフォームデータを送信するURLを設定することで実行できます。
送信されるデータは、まず(キーと値のペアで)辞書の形式で保存され、次に urllib.parse
モジュールにある urlencode
関数を使用して URL エンコードされます。
POSTFIELDSオプションを使用すると、HTTP リクエストメソッドを自動的に POST に設定し、
pf` データも扱えるようになります。
from urllib.parse import urlencode
import pycurl
crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://www.code-learner.com/post/')
data = {'field': 'value'}
pf = urlencode(data)
# Sets request method to POST,
# Content-Type header to application/x-www-form-urlencoded
# and data to send in request body.
crl.setopt(crl.POSTFIELDS, pf)
crl.perform()
crl.close()
注意: 別のリクエストメソッドを指定したい場合は、 CUSTOMREQUEST
オプションを使用することができます。
crl.CUSTOMREQUEST` に続く空の逆カンマに、好きなリクエストメソッドの名前を書けばよい。
crl.setopt(crl.CUSTOMREQUEST, '')
例 4:マルチパート POST を使用してファイルをアップロードする
PycURLを使用してHTMLフォームにファイルをアップロードする方法を再現するには、いくつかの方法があります。
-
- POSTリクエストで送信するデータがシステム上のファイルにある場合、まずデータを送信したいURLを設定する必要があります。次に、リクエストメソッドを
HTTPPOST
に指定し、fileupload
オプションを使用して目的のファイルのコンテンツをアップロードします。
- POSTリクエストで送信するデータがシステム上のファイルにある場合、まずデータを送信したいURLを設定する必要があります。次に、リクエストメソッドを
import pycurl
crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://www.code-learner.com/post/')
crl.setopt(crl.HTTPPOST, [
('fileupload', (
# Upload the contents of the file
crl.FORM_FILE, './my-resume.doc',
)),
])
crl.perform()
crl.close()
注意: もし、ファイルの名前やコンテントタイプを変更したい場合は、上記のコードを少し修正することで可能です。
crl.setopt(crl.HTTPPOST, [
('fileupload', (
# Upload the contents of this file
crl.FORM_FILE, './my-resume.doc',
# Specify a file name of your choice
crl.FORM_FILENAME, 'updated-resume.doc',
# Specify a different content type of upload
crl.FORM_CONTENTTYPE, 'application/msword',
)),
])
- メモリ上にあるファイルデータの場合、POSTリクエストの実装で変わるのは、
FORM_FILE
の代わりにFORM_BUFFER
とFORM_BUFFERPTR
を指定することだけです。
import pycurl
crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://www.code-learner.com/post/')
crl.setopt(crl.HTTPPOST, [
('fileupload', (
crl.FORM_BUFFER, 'contact-info.txt',
crl.FORM_BUFFERPTR, 'You can reach me at billy@example.com',
)),
])
crl.perform()
crl.close()
例5:HTTP PUTでファイルをアップロードする
PUTリクエストは、リクエストのボディでファイルをアップロードするために使用できるという事実を除いて、POSTリクエストと性質が似ています。
作成または上書きしたいオブジェクトの URL がわかっている場合に、PUT リクエストを使用します。
基本的にPUTは、対象のURLに現在存在するものを何か別のものに置き換えます。
アップロードしたいデータが物理的なファイルにある場合、まずターゲットURLを設定する必要があり、次にファイルをアップロードしてそれを開きます。
cURLオブジェクトがそのファイルを使用している間、ファイルを開いておくことが重要です。
次に READDATA
を使ってファイルからデータを読み取ります。
最後に、perform
関数を用いてファイルの転送(アップロード)を行い、cURLのセッションを終了します。
最後に、CURL オブジェクトのために最初に開かれたファイルが閉じられます。
import pycurl
crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://www.code-learner.com/post/')
dat_file = open('data.txt')
crl.setopt(crl.UPLOAD, 1)
crl.setopt(crl.READDATA, dat_file)
crl.perform()
crl.close()
dat_file.close()
ファイルのデータがバッファに格納されている場合、PycURLの実装は物理ファイルに格納されたデータのアップロードとほぼ同じですが、若干の変更が加えられています。
BytesIOオブジェクトは、指定された規格を使用してデータをエンコードします。
これは、READDATA
がIO的なオブジェクトを必要とし、エンコードされたデータがPython 3に不可欠であるためです。
エンコードされたデータはバッファに保存され、そのバッファが読み込まれます。
データのアップロードが行われ、アップロードが完了すると、cURLのセッションが終了します。
import pycurl
crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://www.code-learner.com/post/')
data = '{"person":{"name":"billy","email":"billy@example.com"}}'
buffer = BytesIO(data.encode('utf-8'))
crl.setopt(crl.UPLOAD, 1)
crl.setopt(crl.READDATA, buffer)
crl.perform()
crl.close()
例 6: HTTP DELETE リクエストを送信する
もうひとつの重要でよく使われる HTTP メソッドに DELETE があります。
DELETE メソッドは、サーバがターゲット URL で特定されるリソースを削除するよう要求します。
これは、以下のコードにあるように CUSTOMREQUEST
関数を用いて実装することができます。
import pycurl
crl = pycurl.Curl()
crl.setopt(crl.URL, "http://api.example.com/user/148951")
crl.setopt(crl.CUSTOMREQUEST, "DELETE")
crl.perform()
crl.close()
例 7:ファイルへの書き込み
PycURLは、応答をファイルに保存するためにも使用できます。
ファイルを開くには open
関数を使用し、応答はファイルオブジェクトとして返されます。
open関数は次のような形式です。
open(file, mode) という形式である。
fileパラメータは開くファイルのパスと名前を表し、
modeはファイルを開くときのモードを表します。
この例では、レスポンスのエンコードとデコードを避けるために、ファイルをバイナリモード (すなわちwb`) で開くことが重要である。
import pycurl
file = open('pycurl.md','wb')
crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://wiki.python.org/moin/BeginnersGuide')
crl.setopt(crl.WRITEDATA, file)
crl.perform()
crl.close()
結論
このチュートリアルでは、PythonのPycURLインターフェイスについて学びました。
まず、PycURL の一般的な機能の一部と、Python の libcURL ライブラリとの関連について説明しました。
次に、さまざまなオペレーティングシステムに対する PycURL のインストール手順を確認しました。
最後に、HTTP GET、POST、PUT、DELETEメソッドなど、PycURLが提供するさまざまな機能を実証するPycURLの一般的な例をいくつか見ていきました。
このチュートリアルに従った後は、Pythonプログラム内でURLによって特定されるオブジェクトを簡単に取得できるようになるはずです。