requests库
一、http协议原理
http是无状态的应用层协议
二、urllib、urllib2、requests
在python2中,有urllib和urlib2两个包,python3全变成urllib了
urllib和urllib2是相互独立的模块,比如,urllib不能伪造user agent,但是请求参数的构建,需要使用到urllib,所有经常是两者配合使用的;
requests使用了urlib3(多次请求重复使用一个socket)
三、环境准备
http://httpbin.org/
如果将该站点搭建在本地,使用pip安装就可以了
pip install gunicorn httpbin
启动:
gunicorn httpbin:app --bind 0.0.0.0:8000
发送一个http的get请求,获取本机的IP地址
import urllib2
import urllib
URL_IP='http://192.168.74.20:8000/ip'
def use_simple_urllib2():
response=urllib2.urlopen(URL_IP)
print ">>>>Response Headers:"
print response.info()
print ''.join([line for line in response.readlines()])
if __name__ == '__main__':
print ">>>Use Simple urllib2"
use_simple_urllib2()
结果为:
>>>Use Simple urllib2
>>>>Response Headers:
Server: gunicorn/19.7.1
Date: Sat, 08 Apr 2017 13:06:18 GMT
Connection: close
Content-Type: application/json
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Content-Length: 31
{
"origin": "192.168.74.1"
}
使用urllib构建请求参数,使用urllib2发送请求
def use_params_urllib2():
"""
构建请求参数
:return:
"""
params = urllib.urlencode({'param1':'hello','param2':'world'})
print 'Request Params:'
print params
#发送请求
response=urllib2.urlopen('?'.join([URL_GET,'%s'])%params)
#处理响应
print ">>>>Response Headers:"
print response.info()
print ">>>Status code"
print response.getcode()
print ''.join([line for line in response.readlines()])
if __name__ == '__main__':
print ">>>Use Simple urllib2"
use_simple_urllib2()
print ">>>Use params urllib2"
use_params_urllib2()
结果:
>>>Use params urllib2
Request Params:
param2=world¶m1=hello
>>>>Response Headers:
Server: gunicorn/19.7.1
Date: Sat, 08 Apr 2017 13:22:05 GMT
Connection: close
Content-Type: application/json
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Content-Length: 322
>>>Status code
200
{
"args": {
"param1": "hello",
"param2": "world"
},
"headers": {
"Accept-Encoding": "identity",
"Connection": "close",
"Host": "192.168.74.20:8000",
"User-Agent": "Python-urllib/2.7"
},
"origin": "192.168.74.1",
"url": "http://192.168.74.20:8000/get?param2=world¶m1=hello"
}
使用requests模块实现上述功能
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__author__ = 'Charles Chang'
import requests
import urllib2
import urllib
URL_IP='http://192.168.74.20:8000/ip'
URL_GET='http://192.168.74.20:8000/get'
def use_simple_requests():
response=requests.get(URL_IP)
print ">>>>Response Headers:"
print response.headers
print '>>>>Response Body:'
print response.text
def use_params_resuqets():
"""
构建请求参数
:return:
"""
params = {'param1':'hello','param2':'world'}
print 'Request Params:'
print params
#发送请求
response=requests.get(URL_IP,params=params)
#处理响应
print ">>>>Response Headers:"
print response.headers
print ">>>Status code"
print response.status_code
print response.reason
print ">>>>Response Body:"
print response.json()
if __name__ == '__main__':
print ">>>Use Simple urllib2"
use_simple_requests()
print
print ">>>Use params requests"
use_params_resuqets()
结果:
>>>Use Simple urllib2
>>>>Response Headers:
{'Content-Length': '31', 'Server': 'gunicorn/19.7.1', 'Connection': 'close', 'Access-Control-Allow-Credentials': 'true', 'Date': 'Sat, 08 Apr 2017 14:29:38 GMT', 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json'}
>>>>Response Body:
{
"origin": "192.168.74.1"
}
>>>Use params requests
Request Params:
{'param2': 'world', 'param1': 'hello'}
>>>>Response Headers:
{'Content-Length': '31', 'Server': 'gunicorn/19.7.1', 'Connection': 'close', 'Access-Control-Allow-Credentials': 'true', 'Date': 'Sat, 08 Apr 2017 14:29:38 GMT', 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json'}
>>>Status code
200
OK
>>>>Response Body:
{u'origin': u'192.168.74.1'}
四、github api,requests 请求方法
https://developer.github.com/v3/
GET:查看资源
POST:增加资源
PUT:修改资源
DELETE:删除资源
HEAD:查看响应头
OPTIONS:查看可用请求方法
PATCH:使用少量的json格式的数据去更新数据的方式;
| Verb | Description |
|---|---|
HEAD |
Can be issued against any resource to get just the HTTP header info. |
GET |
Used for retrieving resources. |
POST |
Used for creating resources. |
PATCH |
Used for updating resources with partial JSON data. For instance, an Issue resource hastitle and body attributes. A PATCH request may accept one or more of the attributes to update the resource. PATCH is a relatively new and uncommon HTTP verb, so resource endpoints also accept POST requests. |
PUT |
Used for replacing resources or collections. For PUT requests with no body attribute, be sure to set the Content-Length header to zero. |
DELETE |
Used for deleting resources. |
requests请求方法调用github api
import json
import requests
URL='https://api.github.com'
def build_uri(endpoint):
return '/'.join([URL,endpoint])
def better_print(json_str):
return json.dumps(json.loads(json_str),indent=4)
def request_method():
response=requests.get(build_uri('users/myuser'),auth=('myuser','mypassword'))
print response.text
print better_print(response.text)
if __name__ == '__main__':
request_method()
结果:
{"login":"CharlesQQ","id":18431718,"avatar_url":"https://avatars2.githubusercontent.com/u/18431718?v=3","gravatar_id":"","url":"https://api.github.com/users/CharlesQQ","html_url":"https://github.com/CharlesQQ","followers_url":"https://api.github.com/users/CharlesQQ/followers","following_url":"https://api.github.com/users/CharlesQQ/following{/other_user}","gists_url":"https://api.github.com/users/CharlesQQ/gists{/gist_id}","starred_url":"https://api.github.com/users/CharlesQQ/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CharlesQQ/subscriptions","organizations_url":"https://api.github.com/users/CharlesQQ/orgs","repos_url":"https://api.github.com/users/CharlesQQ/repos","events_url":"https://api.github.com/users/CharlesQQ/events{/privacy}","received_events_url":"https://api.github.com/users/CharlesQQ/received_events","type":"User","site_admin":false,"name":null,"company":null,"blog":null,"location":null,"email":null,"hireable":null,"bio":null,"public_repos":7,"public_gists":0,"followers":0,"following":8,"created_at":"2016-04-13T00:58:55Z","updated_at":"2017-04-08T14:36:42Z","private_gists":0,"total_private_repos":0,"owned_private_repos":0,"disk_usage":14729,"collaborators":0,"two_factor_authentication":false,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
{
"disk_usage": 14729,
"private_gists": 0,
"public_repos": 7,
"site_admin": false,
"subscriptions_url": "https://api.github.com/users/CharlesQQ/subscriptions",
"gravatar_id": "",
"hireable": null,
"id": 18431718,
"followers_url": "https://api.github.com/users/CharlesQQ/followers",
"following_url": "https://api.github.com/users/CharlesQQ/following{/other_user}",
"collaborators": 0,
"total_private_repos": 0,
"blog": null,
"followers": 0,
"location": null,
"type": "User",
"email": null,
"bio": null,
"gists_url": "https://api.github.com/users/CharlesQQ/gists{/gist_id}",
"owned_private_repos": 0,
"company": null,
"events_url": "https://api.github.com/users/CharlesQQ/events{/privacy}",
"html_url": "https://github.com/CharlesQQ",
"updated_at": "2017-04-08T14:36:42Z",
"plan": {
"collaborators": 0,
"name": "free",
"private_repos": 0,
"space": 976562499
},
"received_events_url": "https://api.github.com/users/CharlesQQ/received_events",
"starred_url": "https://api.github.com/users/CharlesQQ/starred{/owner}{/repo}",
"public_gists": 0,
"name": null,
"organizations_url": "https://api.github.com/users/CharlesQQ/orgs",
"url": "https://api.github.com/users/CharlesQQ",
"created_at": "2016-04-13T00:58:55Z",
"avatar_url": "https://avatars2.githubusercontent.com/u/18431718?v=3",
"repos_url": "https://api.github.com/users/CharlesQQ/repos",
"following": 8,
"login": "CharlesQQ",
"two_factor_authentication": false
}
五、带参数的请求
方式1:
search_product.html?cat=19283377&...
params: requests.get(url,params={'key1':''value1})
方式2:表单数据提交
Content-Type: application/x-www-form-urlencoded
requests.post(url,data={'key1':'value1','keys':'value2'})
方式3:json参数提交
Content-type:application/json
requests.post(url,json={'key1':'value1','key2':'value2'})
使用params获取user信息
def params_requests():
response=requests.get(build_uri('users'),params={'since':11})
print better_print(response.text)
print response.request.headers
print response.url
if __name__ == '__main__':
params_requests()
结果:
{
"following_url": "https://api.github.com/users/tomtt/following{/other_user}",
"events_url": "https://api.github.com/users/tomtt/events{/privacy}",
"organizations_url": "https://api.github.com/users/tomtt/orgs",
"url": "https://api.github.com/users/tomtt",
"gists_url": "https://api.github.com/users/tomtt/gists{/gist_id}",
"html_url": "https://github.com/tomtt",
"subscriptions_url": "https://api.github.com/users/tomtt/subscriptions",
"avatar_url": "https://avatars1.githubusercontent.com/u/31?v=3",
"repos_url": "https://api.github.com/users/tomtt/repos",
"received_events_url": "https://api.github.com/users/tomtt/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/tomtt/starred{/owner}{/repo}",
"site_admin": false,
"login": "tomtt",
"type": "User",
"id": 31,
"followers_url": "https://api.github.com/users/tomtt/followers"
},
{
"following_url": "https://api.github.com/users/railsjitsu/following{/other_user}",
"events_url": "https://api.github.com/users/railsjitsu/events{/privacy}",
"organizations_url": "https://api.github.com/users/railsjitsu/orgs",
"url": "https://api.github.com/users/railsjitsu",
"gists_url": "https://api.github.com/users/railsjitsu/gists{/gist_id}",
"html_url": "https://github.com/railsjitsu",
"subscriptions_url": "https://api.github.com/users/railsjitsu/subscriptions",
"avatar_url": "https://avatars1.githubusercontent.com/u/32?v=3",
"repos_url": "https://api.github.com/users/railsjitsu/repos",
"received_events_url": "https://api.github.com/users/railsjitsu/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/railsjitsu/starred{/owner}{/repo}",
"site_admin": false,
"login": "railsjitsu",
"type": "User",
"id": 32,
"followers_url": "https://api.github.com/users/railsjitsu/followers"
},
{
"following_url": "https://api.github.com/users/nitay/following{/other_user}",
"events_url": "https://api.github.com/users/nitay/events{/privacy}",
"organizations_url": "https://api.github.com/users/nitay/orgs",
"url": "https://api.github.com/users/nitay",
"gists_url": "https://api.github.com/users/nitay/gists{/gist_id}",
"html_url": "https://github.com/nitay",
"subscriptions_url": "https://api.github.com/users/nitay/subscriptions",
"avatar_url": "https://avatars1.githubusercontent.com/u/34?v=3",
"repos_url": "https://api.github.com/users/nitay/repos",
"received_events_url": "https://api.github.com/users/nitay/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/nitay/starred{/owner}{/repo}",
"site_admin": false,
"login": "nitay",
"type": "User",
"id": 34,
"followers_url": "https://api.github.com/users/nitay/followers"
},
{
"following_url": "https://api.github.com/users/kevwil/following{/other_user}",
"events_url": "https://api.github.com/users/kevwil/events{/privacy}",
"organizations_url": "https://api.github.com/users/kevwil/orgs",
"url": "https://api.github.com/users/kevwil",
"gists_url": "https://api.github.com/users/kevwil/gists{/gist_id}",
"html_url": "https://github.com/kevwil",
"subscriptions_url": "https://api.github.com/users/kevwil/subscriptions",
"avatar_url": "https://avatars1.githubusercontent.com/u/35?v=3",
"repos_url": "https://api.github.com/users/kevwil/repos",
"received_events_url": "https://api.github.com/users/kevwil/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/kevwil/starred{/owner}{/repo}",
"site_admin": false,
"login": "kevwil",
"type": "User",
"id": 35,
"followers_url": "https://api.github.com/users/kevwil/followers"
},
{
"following_url": "https://api.github.com/users/KirinDave/following{/other_user}",
"events_url": "https://api.github.com/users/KirinDave/events{/privacy}",
"organizations_url": "https://api.github.com/users/KirinDave/orgs",
"url": "https://api.github.com/users/KirinDave",
"gists_url": "https://api.github.com/users/KirinDave/gists{/gist_id}",
"html_url": "https://github.com/KirinDave",
"subscriptions_url": "https://api.github.com/users/KirinDave/subscriptions",
"avatar_url": "https://avatars1.githubusercontent.com/u/36?v=3",
"repos_url": "https://api.github.com/users/KirinDave/repos",
"received_events_url": "https://api.github.com/users/KirinDave/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/KirinDave/starred{/owner}{/repo}",
"site_admin": false,
"login": "KirinDave",
"type": "User",
"id": 36,
"followers_url": "https://api.github.com/users/KirinDave/followers"
},
{
"following_url": "https://api.github.com/users/jamesgolick/following{/other_user}",
"events_url": "https://api.github.com/users/jamesgolick/events{/privacy}",
"organizations_url": "https://api.github.com/users/jamesgolick/orgs",
"url": "https://api.github.com/users/jamesgolick",
"gists_url": "https://api.github.com/users/jamesgolick/gists{/gist_id}",
"html_url": "https://github.com/jamesgolick",
"subscriptions_url": "https://api.github.com/users/jamesgolick/subscriptions",
"avatar_url": "https://avatars1.githubusercontent.com/u/37?v=3",
"repos_url": "https://api.github.com/users/jamesgolick/repos",
"received_events_url": "https://api.github.com/users/jamesgolick/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/jamesgolick/starred{/owner}{/repo}",
"site_admin": false,
"login": "jamesgolick",
"type": "User",
"id": 37,
"followers_url": "https://api.github.com/users/jamesgolick/followers"
},
{
"following_url": "https://api.github.com/users/atmos/following{/other_user}",
"events_url": "https://api.github.com/users/atmos/events{/privacy}",
"organizations_url": "https://api.github.com/users/atmos/orgs",
"url": "https://api.github.com/users/atmos",
"gists_url": "https://api.github.com/users/atmos/gists{/gist_id}",
"html_url": "https://github.com/atmos",
"subscriptions_url": "https://api.github.com/users/atmos/subscriptions",
"avatar_url": "https://avatars0.githubusercontent.com/u/38?v=3",
"repos_url": "https://api.github.com/users/atmos/repos",
"received_events_url": "https://api.github.com/users/atmos/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/atmos/starred{/owner}{/repo}",
"site_admin": false,
"login": "atmos",
"type": "User",
"id": 38,
"followers_url": "https://api.github.com/users/atmos/followers"
},
{
"following_url": "https://api.github.com/users/errfree/following{/other_user}",
"events_url": "https://api.github.com/users/errfree/events{/privacy}",
"organizations_url": "https://api.github.com/users/errfree/orgs",
"url": "https://api.github.com/users/errfree",
"gists_url": "https://api.github.com/users/errfree/gists{/gist_id}",
"html_url": "https://github.com/errfree",
"subscriptions_url": "https://api.github.com/users/errfree/subscriptions",
"avatar_url": "https://avatars1.githubusercontent.com/u/44?v=3",
"repos_url": "https://api.github.com/users/errfree/repos",
"received_events_url": "https://api.github.com/users/errfree/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/errfree/starred{/owner}{/repo}",
"site_admin": false,
"login": "errfree",
"type": "Organization",
"id": 44,
"followers_url": "https://api.github.com/users/errfree/followers"
},
{
"following_url": "https://api.github.com/users/mojodna/following{/other_user}",
"events_url": "https://api.github.com/users/mojodna/events{/privacy}",
"organizations_url": "https://api.github.com/users/mojodna/orgs",
"url": "https://api.github.com/users/mojodna",
"gists_url": "https://api.github.com/users/mojodna/gists{/gist_id}",
"html_url": "https://github.com/mojodna",
"subscriptions_url": "https://api.github.com/users/mojodna/subscriptions",
"avatar_url": "https://avatars1.githubusercontent.com/u/45?v=3",
"repos_url": "https://api.github.com/users/mojodna/repos",
"received_events_url": "https://api.github.com/users/mojodna/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/mojodna/starred{/owner}{/repo}",
"site_admin": false,
"login": "mojodna",
"type": "User",
"id": 45,
"followers_url": "https://api.github.com/users/mojodna/followers"
},
{
"following_url": "https://api.github.com/users/bmizerany/following{/other_user}",
"events_url": "https://api.github.com/users/bmizerany/events{/privacy}",
"organizations_url": "https://api.github.com/users/bmizerany/orgs",
"url": "https://api.github.com/users/bmizerany",
"gists_url": "https://api.github.com/users/bmizerany/gists{/gist_id}",
"html_url": "https://github.com/bmizerany",
"subscriptions_url": "https://api.github.com/users/bmizerany/subscriptions",
"avatar_url": "https://avatars1.githubusercontent.com/u/46?v=3",
"repos_url": "https://api.github.com/users/bmizerany/repos",
"received_events_url": "https://api.github.com/users/bmizerany/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/bmizerany/starred{/owner}{/repo}",
"site_admin": false,
"login": "bmizerany",
"type": "User",
"id": 46,
"followers_url": "https://api.github.com/users/bmizerany/followers"
},
{
"following_url": "https://api.github.com/users/jnewland/following{/other_user}",
"events_url": "https://api.github.com/users/jnewland/events{/privacy}",
"organizations_url": "https://api.github.com/users/jnewland/orgs",
"url": "https://api.github.com/users/jnewland",
"gists_url": "https://api.github.com/users/jnewland/gists{/gist_id}",
"html_url": "https://github.com/jnewland",
"subscriptions_url": "https://api.github.com/users/jnewland/subscriptions",
"avatar_url": "https://avatars1.githubusercontent.com/u/47?v=3",
"repos_url": "https://api.github.com/users/jnewland/repos",
"received_events_url": "https://api.github.com/users/jnewland/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/jnewland/starred{/owner}{/repo}",
"site_admin": true,
"login": "jnewland",
"type": "User",
"id": 47,
"followers_url": "https://api.github.com/users/jnewland/followers"
},
{
"following_url": "https://api.github.com/users/joshknowles/following{/other_user}",
"events_url": "https://api.github.com/users/joshknowles/events{/privacy}",
"organizations_url": "https://api.github.com/users/joshknowles/orgs",
"url": "https://api.github.com/users/joshknowles",
"gists_url": "https://api.github.com/users/joshknowles/gists{/gist_id}",
"html_url": "https://github.com/joshknowles",
"subscriptions_url": "https://api.github.com/users/joshknowles/subscriptions",
"avatar_url": "https://avatars0.githubusercontent.com/u/48?v=3",
"repos_url": "https://api.github.com/users/joshknowles/repos",
"received_events_url": "https://api.github.com/users/joshknowles/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/joshknowles/starred{/owner}{/repo}",
"site_admin": false,
"login": "joshknowles",
"type": "User",
"id": 48,
"followers_url": "https://api.github.com/users/joshknowles/followers"
},
{
"following_url": "https://api.github.com/users/hornbeck/following{/other_user}",
"events_url": "https://api.github.com/users/hornbeck/events{/privacy}",
"organizations_url": "https://api.github.com/users/hornbeck/orgs",
"url": "https://api.github.com/users/hornbeck",
"gists_url": "https://api.github.com/users/hornbeck/gists{/gist_id}",
"html_url": "https://github.com/hornbeck",
"subscriptions_url": "https://api.github.com/users/hornbeck/subscriptions",
"avatar_url": "https://avatars0.githubusercontent.com/u/49?v=3",
"repos_url": "https://api.github.com/users/hornbeck/repos",
"received_events_url": "https://api.github.com/users/hornbeck/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/hornbeck/starred{/owner}{/repo}",
"site_admin": false,
"login": "hornbeck",
"type": "User",
"id": 49,
"followers_url": "https://api.github.com/users/hornbeck/followers"
},
{
"following_url": "https://api.github.com/users/jwhitmire/following{/other_user}",
"events_url": "https://api.github.com/users/jwhitmire/events{/privacy}",
"organizations_url": "https://api.github.com/users/jwhitmire/orgs",
"url": "https://api.github.com/users/jwhitmire",
"gists_url": "https://api.github.com/users/jwhitmire/gists{/gist_id}",
"html_url": "https://github.com/jwhitmire",
"subscriptions_url": "https://api.github.com/users/jwhitmire/subscriptions",
"avatar_url": "https://avatars0.githubusercontent.com/u/50?v=3",
"repos_url": "https://api.github.com/users/jwhitmire/repos",
"received_events_url": "https://api.github.com/users/jwhitmire/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/jwhitmire/starred{/owner}{/repo}",
"site_admin": false,
"login": "jwhitmire",
"type": "User",
"id": 50,
"followers_url": "https://api.github.com/users/jwhitmire/followers"
},
{
"following_url": "https://api.github.com/users/elbowdonkey/following{/other_user}",
"events_url": "https://api.github.com/users/elbowdonkey/events{/privacy}",
"organizations_url": "https://api.github.com/users/elbowdonkey/orgs",
"url": "https://api.github.com/users/elbowdonkey",
"gists_url": "https://api.github.com/users/elbowdonkey/gists{/gist_id}",
"html_url": "https://github.com/elbowdonkey",
"subscriptions_url": "https://api.github.com/users/elbowdonkey/subscriptions",
"avatar_url": "https://avatars0.githubusercontent.com/u/51?v=3",
"repos_url": "https://api.github.com/users/elbowdonkey/repos",
"received_events_url": "https://api.github.com/users/elbowdonkey/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/elbowdonkey/starred{/owner}{/repo}",
"site_admin": false,
"login": "elbowdonkey",
"type": "User",
"id": 51,
"followers_url": "https://api.github.com/users/elbowdonkey/followers"
},
{
"following_url": "https://api.github.com/users/reinh/following{/other_user}",
"events_url": "https://api.github.com/users/reinh/events{/privacy}",
"organizations_url": "https://api.github.com/users/reinh/orgs",
"url": "https://api.github.com/users/reinh",
"gists_url": "https://api.github.com/users/reinh/gists{/gist_id}",
"html_url": "https://github.com/reinh",
"subscriptions_url": "https://api.github.com/users/reinh/subscriptions",
"avatar_url": "https://avatars0.githubusercontent.com/u/52?v=3",
"repos_url": "https://api.github.com/users/reinh/repos",
"received_events_url": "https://api.github.com/users/reinh/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/reinh/starred{/owner}{/repo}",
"site_admin": false,
"login": "reinh",
"type": "User",
"id": 52,
"followers_url": "https://api.github.com/users/reinh/followers"
},
{
"following_url": "https://api.github.com/users/knzconnor/following{/other_user}",
"events_url": "https://api.github.com/users/knzconnor/events{/privacy}",
"organizations_url": "https://api.github.com/users/knzconnor/orgs",
"url": "https://api.github.com/users/knzconnor",
"gists_url": "https://api.github.com/users/knzconnor/gists{/gist_id}",
"html_url": "https://github.com/knzconnor",
"subscriptions_url": "https://api.github.com/users/knzconnor/subscriptions",
"avatar_url": "https://avatars0.githubusercontent.com/u/53?v=3",
"repos_url": "https://api.github.com/users/knzconnor/repos",
"received_events_url": "https://api.github.com/users/knzconnor/received_events",
"gravatar_id": "",
"starred_url": "https://api.github.com/users/knzconnor/starred{/owner}{/repo}",
"site_admin": false,
"login": "knzconnor",
"type": "User",
"id": 53,
"followers_url": "https://api.github.com/users/knzconnor/followers"
}
]
{'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.10.0'}
https://api.github.com/users?since=11
使用patch修改数据
def json_request():
response=requests.patch(build_uri('user'),auth=('charlesQQ','mypass'),
json={'name':'charlesQQ11','email':'charles_ali@qq.com'})
print better_print(response.text)
print response.request.headers
print response.request.body
print response.status_code
{
"disk_usage": 14729,
"private_gists": 0,
"public_repos": 7,
"site_admin": false,
"subscriptions_url": "https://api.github.com/users/CharlesQQ/subscriptions",
"gravatar_id": "",
"hireable": null,
"id": 18431718,
"followers_url": "https://api.github.com/users/CharlesQQ/followers",
"following_url": "https://api.github.com/users/CharlesQQ/following{/other_user}",
"collaborators": 0,
"total_private_repos": 0,
"blog": null,
"followers": 0,
"location": null,
"type": "User",
"email": "charles_ali@qq.com",
"bio": null,
"gists_url": "https://api.github.com/users/CharlesQQ/gists{/gist_id}",
"owned_private_repos": 0,
"company": null,
"events_url": "https://api.github.com/users/CharlesQQ/events{/privacy}",
"html_url": "https://github.com/CharlesQQ",
"updated_at": "2017-04-08T14:36:42Z",
"plan": {
"collaborators": 0,
"name": "free",
"private_repos": 0,
"space": 976562499
},
"received_events_url": "https://api.github.com/users/CharlesQQ/received_events",
"starred_url": "https://api.github.com/users/CharlesQQ/starred{/owner}{/repo}",
"public_gists": 0,
"name": "charlesQQ11",
"organizations_url": "https://api.github.com/users/CharlesQQ/orgs",
"url": "https://api.github.com/users/CharlesQQ",
"created_at": "2016-04-13T00:58:55Z",
"avatar_url": "https://avatars2.githubusercontent.com/u/18431718?v=3",
"repos_url": "https://api.github.com/users/CharlesQQ/repos",
"following": 8,
"login": "CharlesQQ",
"two_factor_authentication": false
}
{'Content-Length': '54', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.10.0', 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Authorization': 'Basic Y2hhcmxlc1FROnN0YXJ0MzMzMzM='}
{"name": "charlesQQ11", "email": "charles_ali@qq.com"}
200
使用post增加数据
def json_request():
#response=requests.patch(build_uri('user'),auth=('charlesQQ','mypass'),
# json={'name':'charlesQQ11','email':'charles_ali@qq.com'})
response=requests.post(build_uri('user/emails'),auth=('charlesQQ','start33333'),json=['qq_c1231@163.com'])
print better_print(response.text)
print response.request.headers
print response.request.body
print response.status_code
六、请求异常处理
一般在我们调用第三方服务的时候,难以避免的是第三方服务调用出现异常,这种时候,就需要使用异常处理,来保证程序可以正常运行;
requests的异常处理,需要使用其exceptions类来实现;
将超时时间设置为0.1秒,来触发超时异常
import requests
from requests import exceptions
def timeout_request():
try:
response=requests.get(build_uri('user/emails'),timeout=0.1)
response.raise_for_status()
except exceptions.Timeout as e:
print e.message
except exceptions.HTTPError as e:
print e.message
else:
print response.text
print response.status_code
调用结果:
HTTPSConnectionPool(host='api.github.com', port=443): Max retries exceeded with url: /user/emails (Caused by ConnectTimeoutError(<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x0000000003148CF8>, 'Connection to api.github.com timed out. (connect timeout=0.1)'))
将超时时间设置为10s,触发401错误
def timeout_request():
try:
response=requests.get(build_uri('user/emails'),timeout=10)
response.raise_for_status()
except exceptions.Timeout as e:
print e.message
except exceptions.HTTPError as e:
print e.message
else:
print response.text
print response.status_code
调用结果:
401 Client Error: Unauthorized for url: https://api.github.com/user/emails
七、自定义request
requests通过urlib3实现可以hold住整个socket,通过session实现;
发送的request包,包含发送的body,headers,auth,proxy,timeout,verify等,回复消息response为text,json等;
有时间去研究源码吧
def hard_requests():
from requests import Request,Session
s=Session()
headers={'User-Agent':'fake1.3.4'}
req=Request('GET',build_uri('user/emails'),auth=('myuser','mypass'),headers=headers)
prepared=req.prepare()
print prepared.body
print prepared.headers
resp=s.send(prepared,timeout=5)
print resp.status_code
print resp.request.headers
print resp.text
结果:
None
{'Authorization': 'Basic Y2hhcmxlc1FROnN0YXJ0MzMzMzM=', 'User-Agent': 'fake1.3.4'}
200
{'Authorization': 'Basic Y2hhcmxlc1FROnN0YXJ0MzMzMzM=', 'User-Agent': 'fake1.3.4'}
[{"email":"qq_c123@163.com","primary":false,"verified":false,"visibility":null},{"email":"charles_ali@qq.com","primary":true,"verified":true,"visibility":"public"},{"email":"qq_c1231@163.com","primary":false,"verified":false,"visibility":null}]
八、响应基本API
Response对象的API:
status_code:如下
400:Bad request,请求服务器端无法解析; 401:unauthorized,请求没有认证; 403:forbidden; 404:Not found;
500:内部错误;
reason:
headers:
url:
history:
elapsed:
request:
encoding:
raw:读取原始的对象
content:string类型:
text:unicode;
json:
下面分别举例介绍
status_code和reason
import requests
response = requests.get('https://api.github.com')
>>> response.status_code
200
>>> response.reason
'OK'
响应headers
>>> response.headers
{'X-XSS-Protection': '1; mode=block', 'Content-Security-Policy': "default-src 'none'", 'Access-Control-Expose-Headers': 'ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval', 'Transfer-Encoding': 'chunked', 'Access-Control-Allow-Origin': '*', 'X-Frame-Options': 'deny', 'Status': '200 OK', 'X-Served-By': 'eef8b8685a106934dcbb4b7c59fba0bf', 'X-GitHub-Request-Id': '059D:17F65:2FAC88D:3DE5D57:58EA0875', 'ETag': 'W/"7dc470913f1fe9bb6c7355b50a0737bc"', 'Date': 'Sun, 09 Apr 2017 10:09:57 GMT', 'X-RateLimit-Remaining': '38', 'Strict-Transport-Security': 'max-age=31536000; includeSubdomains; preload', 'Server': 'GitHub.com', 'X-GitHub-Media-Type': 'github.v3; format=json', 'X-Content-Type-Options': 'nosniff', 'Content-Encoding': 'gzip', 'Vary': 'Accept, Accept-Encoding', 'X-RateLimit-Limit': '60', 'Cache-Control': 'public, max-age=60, s-maxage=60', 'Content-Type': 'application/json; charset=utf-8', 'X-RateLimit-Reset': '1491735173'}
响应url
>>> response.url u'https://api.github.com/'
响应history
>>> response.history #如果没有重定向,默认为空
[]
>>> response = requests.get('http://api.github.com') #一般访问http,会跳转到https
>>> response.history
[<Response [301]>]
响应时间
>>> response.elapsed datetime.timedelta(0, 3, 158723)
可以调用的方法
>>> dir(response) ['__attrs__', '__bool__', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getstate__', '__hash__', '__init__', '__iter__', '__module__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_content', '_content_consumed', 'apparent_encoding', 'close', 'connection', 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history', 'is_permanent_redirect', 'is_redirect', 'iter_content', 'iter_lines', 'json', 'links', 'ok', 'raise_for_status', 'raw', 'reason', 'request', 'status_code', 'text', 'url']
请求对象和请求头
>>> response.request
<PreparedRequest [GET]>
>>> response.request.headers
{'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.6.0 CPython/2.7.5 Linux/3.10.0-327.el7.x86_64'}
请求的编码
>>> response.encoding 'utf-8'
响应的内容,content为str类型
>>> response.raw.read(10)
''
>>>
>>>
>>> response.content
'{"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}"}'
响应内容,text为unicode类型
>>> response.text
u'{"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对象
>>> response.json(
... )
{u'issues_url': u'https://api.github.com/issues', u'current_user_repositories_url': u'https://api.github.com/user/repos{?type,page,per_page,sort}', u'rate_limit_url': u'https://api.github.com/rate_limit', u'repository_search_url': u'https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}', u'user_organizations_url': u'https://api.github.com/user/orgs', u'commit_search_url': u'https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}', u'repository_url': u'https://api.github.com/repos/{owner}/{repo}', u'emojis_url': u'https://api.github.com/emojis', u'hub_url': u'https://api.github.com/hub', u'keys_url': u'https://api.github.com/user/keys', u'following_url': u'https://api.github.com/user/following{/target}', u'emails_url': u'https://api.github.com/user/emails', u'authorizations_url': u'https://api.github.com/authorizations', u'code_search_url': u'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}', u'followers_url': u'https://api.github.com/user/followers', u'public_gists_url': u'https://api.github.com/gists/public', u'organization_url': u'https://api.github.com/orgs/{org}', u'gists_url': u'https://api.github.com/gists{/gist_id}', u'feeds_url': u'https://api.github.com/feeds', u'user_search_url': u'https://api.github.com/search/users?q={query}{&page,per_page,sort,order}', u'user_url': u'https://api.github.com/users/{user}', u'events_url': u'https://api.github.com/events', u'organization_repositories_url': u'https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}', u'current_user_url': u'https://api.github.com/user', u'issue_search_url': u'https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}', u'notifications_url': u'https://api.github.com/notifications', u'starred_url': u'https://api.github.com/user/starred{/owner}{/repo}', u'starred_gists_url': u'https://api.github.com/gists/starred', u'current_user_authorizations_html_url': u'https://github.com/settings/connections/applications{/client_id}', u'user_repositories_url': u'https://api.github.com/users/{user}/repos{?type,page,per_page,sort}', u'team_url': u'https://api.github.com/teams'}
>>> response.json()['team_url'] #访问json的对象
u'https://api.github.com/teams'
九、下载图片/文件
图片/文件下载过程
浏览器模拟-->构建request(调试策略)-->读取流data-->打开文件,存入数据
有一些返回的context的内容是没有办法读取的,只有通过流的方式保存到文件中
import requests
def download_image():
"""
demo:下载图片
:return:
"""
url= "http://img0.tech2ipo.com/upload/img/article/2015/06/1434420238601.png"
headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'}
response=requests.get(url,headers=headers,stream=True)
with open('demo.png','wb') as fd:
for chunk in response.iter_content(128):
fd.write(chunk)
print response.status_code
# print response.reason
# print response.content
使用上下午文管理的方式,读物数据流,写入文件,最后关闭流
def download_image_improved():
"""
demo:下载图片
:return:
"""
#伪造headers信息
headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'}
#限定url
url= "http://img0.tech2ipo.com/upload/img/article/2015/06/1434420238601.png"
response=requests.get(url,headers=headers,stream=True)
from contextlib import closing
with closing(requests.get(url,headers=headers,stream=True)) as response:
#打开文件
with open('demo.png','wb') as fd:
#每128写入一次
for chunk in response.iter_content(128):
fd.write(chunk)
十、事件钩子(Event hooks)
类似于js中的回调函数;
IO请求-->response-->回调函数
说白了,就是异步请求,request发出之后,直接返回,剩余的IO请求,由回调函数处理;
异步处理demo
import requests
def get_key_info(response,*args,**kwargs):
"""
回调函数
:return:
"""
print response.headers['Content-Type']
def main():
"""
主程序
:return:
"""
requests.get('https://api.github.com',hooks=dict(response=get_key_info))
main()
执行结果:
application/json; charset=utf-8
十一、HTTP认证
1、http基本认证
requests a protected resource-->requests a username:password-->sends username:password-->returns requests resource
import requests
BASE_URL='https://api.github.com'
def construct_url(end_point):
return '/'.join([BASE_URL,end_point])
def basic_auth():
"""
基本认证
:return:
"""
response=requests.get(construct_url('user'),auth=('imoocdeo','imoocdeo123'))
print response.text
print response.request.headers
basic_auth()
打印结果:
{"message":"Bad credentials","documentation_url":"https://developer.github.com/v3"}
{'Authorization': 'Basic aW1vb2NkZW86aW1vb2NkZW8xMjM=', 'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.10.0'}
这里字符串 aW1vb2NkZW86aW1vb2NkZW8xMjM=是使用base64编码的结果
在终端打开bpython(pip install bpython安装)
>>> import base64
>>>
>>> base64.b64decode('aW1vb2NkZW86aW1vb2NkZW8xMjM=')
'imoocdeo:imoocdeo123' #是用户名和密码拼凑起来的,但是这样可能不安全
2、OAUTH认证
https://www.codewars.com/ 使用的登录认证方式
APP---github

github生成access_token: https://github.com/settings/tokens-->Generate new token-->选择该token拥有的权限
def basic_oauth():
headers={'Authorization':'token 51684c8452ff83556f1a6705d2d85d7f68cd5ca7'}
#user/emails,通过请求头把token带过去
response=requests.get(construct_url('user/emails'),headers=headers)
print response.request.headers
print response.text
print response.status_code
basic_oauth()
打印结果:
{'Authorization': 'token 51684c8452ff83556f1a6705d2d85d7f68cd5ca7', 'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.10.0'}
[{"email":"qq_c123@163.com","primary":false,"verified":false,"visibility":null},{"email":"charles_ali@qq.com","primary":true,"verified":true,"visibility":"public"},{"email":"qq_c1231@163.com","primary":false,"verified":false,"visibility":null}]
200
使用python自带的语法糖类实现上述内容,__call__可以将实例化的对象当做类进行实例化调用,即将实例化的对象在加(),就可以调用__call__函数,f()();
from requests.auth import AuthBase
class GithubAuth(AuthBase):
def __init__(self,token):
self.token=token
def __call__(self, r):
#request 加headers
r.headers['Authorization']=' '.join(['token',self.token])
print r
return r
def oauth_advaced():
auth=GithubAuth('51684c8452ff83556f1a6705d2d85d7f68cd5ca7')
response=requests.get(construct_url('user/emails'),auth=auth)
print response.text
oauth_advaced()
调用结果:
<PreparedRequest [GET]>
[{"email":"qq_c123@163.com","primary":false,"verified":false,"visibility":null},{"email":"charles_ali@qq.com","primary":true,"verified":true,"visibility":"public"},{"email":"qq_c1231@163.com","primary":false,"verified":false,"visibility":null}]
十二、requests库的proxy代理
import requests
proxies={'http':'sock5://127.0.0.1:1080','https':'sock5://127.0.0.1:1080'} #设置代理地址
url='https://www.facebook.com'
response=requests.get(url,proxies=proxies,timeout=10)
十三、Session和cookie
cookie:
浏览器请求(无cookie)-->服务器-->HTTP响应(响应头有set cookie,设置有效期,权限范围等等)-->解析cookie保存本地-->HTTP请求(携带cookie)--->解析cookie识别信息--HTTP响应
缺点:cookie是在浏览器端的,每次请求,都要携带cookie,消耗带宽;cookie可以伪造,不安全;
session:
浏览器HTTP请求-->服务器存储session-->HTTP响应(set cookie-session-id 叫做session id的cookie)-->解析cookie保存本地(这个cookie非常小,仅含有session id)-->解析session id(到存储中查,该session id对于的用户信息,权限信息是什么)-->HTTP响应
浙公网安备 33010602011771号