Python Requestsモジュールについて

[参照]
Pythonプロフェッショナルプログラミング第2版

#Requests:HTTP for Humans
http://docs.python-requests.org/en/latest


#RESTとは

RESTはソフトウェアアーキテクチャーのひとつ。
ソフトウェアの設計原則の集合。

「REST」「REST API」という単語は、「HTTP」上で動作するSOAPやRPCではないAPI」の意味で使われることが多い。

#REST APIの特徴

- HTTP上で動作する
- データはリソースと呼ばれる
- REST APIで使用可能なリソースは、一意なURLを持っている。
- GET/POST/PUT/DELETEなどのHTTPメソッドはそれぞれ、取得/保存/上書き/削除などのリソースの操作と対応している。
- JSONやXMLなどのフォーマットでデータを送受信する
- リクエストの成功や失敗などの処理結果はステータスコードで表す

REST APIを使用するには、HTTPクライアントを利用する。
・シェル上のコマンドやシェルスクリプトではcurlを使う。
・プログラム中から使用する場合はHTTPクライアントライブラリを使う。

https://ja.wikipedia.org/wiki/REST

---

#以下の説明内容のまとめ

1.Requestsの導入
2.テスト用サーバーの導入(httpbinのテスト)
3.リクエスト
　•3-1 GETリクエストの送信
　•3-2 POSTリクエストの送信
　•3-3 JSON形式でPOSTリクエストを送信する
　•3-4 GET/POST以外のHTTPメソッドの使用

---

#1.Requestsの導入

pipコマンドを使用する。

```py

$ pip install requests

```

#2.テスト用サーバーの導入

・Requestsモジュールの動作を試すにはWebサーバーが必要。


#httpbin
※httpbinというモジュールを使用する場合

```py

$ pip install httpbin

```

```py

$ python -m httpbin.core

*Running on http://127.0.0.1:5000

```

※Requestsモジュールから使用する前に、テストサーバーの動作をcurlコマンドで確認してみる。
※テストサーバーを起動した状態で、次のコマンドを実行する。
※正常に動作していれば、JSON形式のレスポンスが表示される。

```bash

$ curl "http://127.0.0.1:5000/get?foo=bar" #GETリクエストをテストサーバーに送信


{
	"args":{　＃argsはGETパラメータ
	"foo":"bar"
},
"headers":{
	"Accept":"*/*",
	"Content-Length:"",
	"Content-Type": "",
	"Host": "127.0.0.1:5000",
	"User-Agent": "curl/7.35.0"
},
"origin":"127.0.0.1",
"url": "http://127.0.0.1:5000"/get?foo=bar"
}

$ curl -x post -d foo=bar http://127.0.0.1:5000/post #postリクエストをテスト　サーバーに送信
{
"args":{},
"data":"", #dataは送信データの本文
"files":{},
"form":{ #formはフォームエンコードされたパラメータ
"foo":"bar"
},
"headers":{
	"Accept":"*/*,
	"Content-Length":"7",
	"Content-Type":"application/x-www-form-urlencoded",
	"Host":"127.0.0.1:5000",
	"User-Agent": "curl/7.35.0"
},
"json":null,
"origin":"127.0.0.1",
"url":"http://127.0.0.1:5000/post"
}

テストサーバーは、リクエストした内容をJSON形式で返してくれる。

```

#3.リクエスト


##3-1.GETリクエストの送信

Requestsを使用してGETリクエストを送信する

```py

# coding utf-8
import pprint
import requests

def main():
	#GETパラメータはparams引数に辞書で指定する

	response = requests.get(
		'http://127.0.0.1:5000/get',
		params={'foo': 'bar'})
	#レスポンスオブジェクトのjsonメソッドを使うと、
	#JSONデータをPythonの辞書オブジェクトを変換して取得できる。
	pprint.pprint(response.json())

if __name__== '__main__':
	main()

```

requests.get関数に対象のURLとparamsキーワード引数でGETパラメーターを指定する。
サーバーからのレスポンスはJSON形式なので、jsonメソッドで辞書に変換してから画面に表示する。
ソースコードを実行すると次のような結果になる。


```py

$ python requests_get.py

{u'args':{u'foo':u'bar'},
u'headers': {u'Accept':u'*/*',
			u'Accept-Encoding': u'gzip,deflate',
			u'Connection':u'keep-alive',
			u'Content-Length': u'',
			u'Content-Type': u'',
			u'Host': u'127.0.0.1:5000',
			u'User-Agent' : u'python-requests/2.5.0 CPython/2.7.8 Linux/3.13.0-35-generic'},
u'origin' : u'127.0.0.1',
u'url' : u'http://127.0.0.1:5000/get?foo=bar'}


```

#3-2.POSTリクエストの送信

Requestsを使用してPOSTリクエストを送信するコード


```py

# coding: utf-8
import pprint
import requests

def main():
	#POSTパラメータは二つ目の引数に辞書で指定する
	response = requests.post(
		'http://127.0.0.1:5000/post',
		{'foo':'bar'})
	#レスポンスオブジェクトのjsonメソッドを使うと、
	#JSONデータをPythonの辞書オブジェクトに変換して取得できる
	pprint.pprint(response.json())

if __name__=='__main__':
　　　main()


```
requests.post関数に対象のURLとPOSTパラメータを指定している。POSTパラメータに辞書を指定すると、URLエンコードされてから送信される。
このソースコードを実行すると次のような結果になる。

```py

$python requests_post.py

{u'args':{},
u''data': u'',
u'data': u'',
u'files':{}
u'form':{u'foo' u'bar'},
u'headers':{u'Accept': u'*/*',
			u'Accept-Encoding': u'gzip, deflate',
			u'Connection':u'keep-alive',
			u'Content-Length': u'7',
			u'Content-Type': u'application/x-www-form-urlencoded',
			u'Host': u'127.0.0.1:5000',
			u'User-Agent': u'python-requests/2.5.0 CPython/2.7.8 Linux/3.13.0-35-generic'},
			u'json': None,
			u'origin': u'127.0.0.1',
			u'url': u'http://127.0.0.1:5000/post'}


```


#3-3.JSON形式でPOSTリクエストを送信する

APIインターフェイスによっては、送信するデータをURLエンコードではなくJSON形式の文字列で要求するものがある。
RequestsでJSON形式の文字列をPOSTリクエストで送信するコードは以下にようになる。


```requests_post_json.py

import pprint
import json
import requests

def main()
	response = requests.post(
		'http://127.0.0.1:5000/post',
		json.dumps({'foo':'bar'}),
		headers={'Content-Type': 'application/json'})
	pprint.pprint(response.json())


if __name__=='__main__':
	main()

```

※json.dumpsで生成した文字列を指定すると、URLエンコードされずにそのままデータが送信される。
※Content-Typeを明示的に指定する必要がある。

※post関数の引数に送信するデータを文字列で指定している。
※文字列を指定した場合、URLエンコードされず送信される。


上記のソースコードを実行すると次の結果となる。

```py


$python requests_post_json.py

{u'args}:{},
u'data': u'{"foo": "bar"} ',
u'files': {},
u'form': {},
u'headers':{u'Accept': u'*/*,
			u''Accept-Encoding': u'gzip, deflate',
			u'Connection': u'keep-alive',
			u'Content-Length': u'14',
			u'Content-Type': u'application/json',
			u'Host': u'127.0.0.1:5000',
			u''User-Agent': u'python-requests/2.5.0 CPython/2.7.8 Linux/3.13.0-35-generic'},
			u'json':{u'foo': u'bar'},
			u'origin': u'127.0.0.1',
			u'url': u'http://127.0.0.1:5000/post'}


```


#3-4.GET/POST以外のHTTPメソッドの使用

APIによってはGET,POST以外のHTTPメソッド(PUT、DELETE、HEAD、OPTIONS)を要求するものがある。
RequestsではGETやPOSTと同様に、これらのメソッドに対応する関数が用意されている。


```py

# coding: utf-8
import requests

def main():
	requests.put('http://127.0.0.1:5000/put',{'foo': 'bar'}) #put
	requests.delete('http://127.0.0.1:5000/delete') #delete
	requests.head('http://127.0.0.1:5000/get') #HEAD
	requests.options('http://127.0.0.1:5000/options') #OPTIONS

if __name__ == '__main__':
	main()


```

上記のソースコードは実行すると、
HTTPのPUT、DELETE、HEAD、OPTIONSメソッドのリクエストをサーバーへ送信し、
レスポンスを取得したら終了する。