Python requests库的使用(二)
1.请求异常处理
请求异常类型:
请求超时处理(timeout):
实现代码:
import requests
from requests import exceptions #引入exceptions
A:请求超时
def timeout_request():
try:
response = requests.get(build_uri('user/emails'), timeout=0.1)
except exceptions.Timeout as e:
print e.message
返回数据:HTTPSConnectionPool(host='api.github.com', port=443): Max retries exceeded with url: /user/emails (Caused by ConnectTimeoutError(<urllib3.connection.VerifiedHTTPSConnection object at 0x02BDEC50>, 'Connection to api.github.com timed out. (connect timeout=0.1)'))
B:未认证时访问,报HTTPError
代码:
def timeout_request():
response = requests.get(build_uri('user/emails'), timeout=10)
print response.text
print response.status_code
返回数据:
{"message":"Requires authentication","documentation_url":"https://developer.github.com/v3"}
401
C:抛出HTTPError异常信息
def timeout_request():
try:
response = requests.get(build_uri('user/emails'), timeout=10)
response.raise_for_status()
except exceptions.HTTPError as e:
print e.message
返回数据:
401 Client Error: Unauthorized for url: https://api.github.com/user/emails #401客户端错误,没有认证的情况下访问url;
注意:以上的两个小程序,通过使用try.....except机制,就合理的处理了发送请求时的各种各样的“拦路虎”,依靠except分支可以帮助我们来处理异常,特别是在调用第三方服务的时候。
2.自定义Requests
requests库进阶部分官方域名:http://www.python-requests.org/en/master/user/advanced/
翻译上图中红色框中的内容:
会话对象允许你在发送请求的时候保留某些参数,它也能够保留会话过程中发送请求的cookie,并且使用urllib3进程池,所以如果你向同一个域名发送多个请求时,底层的TCP链接会被重用,由此会带来一个很明显的性能提高(参见HTTP持久链接)。
Session模块的组成:
代码实现:
def hard_requests():
'''构造请求
'''
from requests import Request, Session #引入Request Session
s = Session()
headers = {'User-Agent': 'fake1.3.4'}
req = Request('GET', build_uri('user/emails'), auth=('caolanmiao', 'key########'), headers=headers)
prepped = req.prepare() #使用prepare()方法准备url
print prepped.body
print prepped.headers
只有以上的代码时的返回结果:
None
{'Authorization': 'Basic aW1vb2NkZW1vOmltb29jZGVtbzEyMw==', 'User-Agent': 'fake1.3.4'}
可见,请求还没有发送出去
'''发送请求
'''
resp = s.send(prepped, timeout=5) #发送请求,使用send()方法
print resp.status_code
print resp.request.headers
print resp.text
加上以上代码后的返回结果:
None
{'Authorization': 'Basic aW1vb2NkZW1vOmltb29jZGVtbzEyMw==', 'User-Agent': 'fake1.3.4'}
200
{'Authorization': 'Basic aW1vb2NkZW1vOmltb29jZGVtbzEyMw==', 'User-Agent': 'fake1.3.4'}
[{"email":"helloworld2@github.com","primary":true,"verified":false,"visibility":"private"},{"email":"hello-world@.123org","primary":false,"verified":false,"visibility":null},
可见,此时请求才发送成功。
通过上面的代码可以看出,使用自定义的方法构造请求,可以随时控制请求的发送时机。
3.处理响应
响应基本API:
代码举例:
# -*- coding: utf-8 -*-
import requests
response = requests.get('https://api.github.com')
print "状态码,具体解释"
print response.status_code, response.reason
print "头部信息"
print response.headers
print "URL 信息"
print response.url
print "redirect 信息"
print response.history
print "耗费时长"
print response.elapsed
print "request 信息"
print response.request.method
print "编码信息"
print response.encoding
print "消息主体内容: byte"
print response.content, type(response.content)
print "消息主体内容: 解析"
print response.text, type(response.text)
print "消息主体内容"
print response.json(), type(response.json())
有关HTTP状态码(status_code)的域名,可以关注维基百科:https://zh.wikipedia.org/zh/HTTP%E7%8A%B6%E6%80%81%E7%A0%81
常见的status_code和reason:
2xx成功:这一类型的状态码,代表请求已成功被服务器接收、理解、并接受。
200 OK 请求已成功,请求所希望的响应头或数据体将随此响应返回
201 Created 请求已经被实现,而且有一个新的资源已经依据请求的需要而建立
202 Accepted 服务器已接受请求,但尚未处理
204 No Content 服务器成功处理了请求,没有返回任何内容
3xx重定向:这类状态码代表需要客户端采取进一步的操作才能完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明
301 Moved Permanently 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的
302 Found 要求客户端执行临时重定向(原始描述短语为“Moved Temporarily”)。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的
304 Not Modified 表示资源未被修改,因为请求头指定的版本If-Modified-Since或If-None-Match。在这种情况下,由于客户端仍然具有以前下载的副本,因此不需要重新传输资源
4xx客户端错误:这类的状态码代表了客户端看起来可能发生了错误,妨碍了服务器的处理。除非响应的是一个HEAD请求,否则服务器就应该返回一个解释当前错误状况的实体,以及这是临时的还是永久性的状况。这些状态码适用于任何请求方法。浏览器应当向用户显示任何包含在此类错误响应中的实体内容。
400 Bad Request 由于明显的客户端错误(例如,格式错误的请求语法,太大的大小,无效的请求消息或欺骗性路由请求),服务器不能或不会处理该请求
401 Unauthorized 类似于403 Forbidden,401语义即“未认证”,即用户没有必要的凭据
403 Forbidden 没有权限;服务器已经理解请求,但是拒绝执行它。与401不同的是,身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交
404 Not Found 请求失败,请求所希望得到的资源未被在服务器上发现,但允许用户的后续请求
5XX:服务器错误,表示服务器无法完成明显有效的请求
500 Internal Server Error 通用错误消息,服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。没有给出具体错误信息
502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应
503 Service Unavailable 由于临时的服务器维护或者过载,服务器当前无法处理请求。这个状况是暂时的,并且将在一段时间以后恢复
通过dir(response),可以查看response的全部API。
4.下载图片/文件
举例:通过下面代码实现下载图片(百度“github”图片中的第一个),下图是实现流程图
# -*- coding: utf -*-
import requests
def download_image():
"""demo: 下载图片, 文件
"""
# 伪造headers信息
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36'} #获取权限,使用Firefox浏览器
# 限定url
url = "http://img3.imgtn.bdimg.com/it/u=2228635891,3833788938&fm=21&gp=0.jpg"
response = requests.get(url, headers=headers, stream=True) #stream=True 流传输
# 打开文件
with open('demo.jpg', 'wb') as fd:
# 每128写入一次
for chunk in response.iter_content(128):
fd.write(chunk)
def download_image_improved():
"""demo: 下载图片
"""
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36'}
url = "http://img3.imgtn.bdimg.com/it/u=2228635891,3833788938&fm=21&gp=0.jpg"
response = requests.get(url, headers=headers, stream=True)
from contextlib import closing
with closing(requests.get(url, headers=headers, stream=True)) as response: #把打开的流stream关闭,以节省资源
with open('demo1.jpg', 'wb') as fd:
for chunk in response.iter_content(128):
fd.write(chunk)
download_image_improved()
如下图,demo.jpg文件已经成功下载到本地了
5.事件钩子
事件钩子(event hooks)模型
# -*- coding: utf-8 -*-
import requests
def get_key_info(response, *args, **kwargs):
"""回调函数
"""
print response.headers['Content-Type']
def main():
"""主程序
"""
requests.get('https://api.github.com', hooks=dict(response=get_key_info))
main()
返回数据:
application/json; charset=utf-8
利用事件钩子的方法可以使得request和response分开,特别是当代码很多的时候,方便管理。
6.Request库--HTTP认证
前面所讲的发送一个请求,得到响应,其实有一个简单的假设,就是通过HTTP通讯,我们访问的所有资源都是可见的,实际上很多时候,为了提高安全性,服务端要验证请求的来源,只有通过验证的请求,服务端才会响应。最简单基本认证的模式,如下图:
对于受保护的服务,在发送请求的时候就要加上一个requests库里的认证参数:auth
实验代码:
# -*- coding: utf-8 -*-
import requests
BASE_URL='https://api.github.com'
def construct_url(end_point):
return '/'.join([BASE_URL,end_point])
def basic_auth():
"""基本认证
"""
response=requests.get(construct_url('user'),auth=('caolanmiao','key######')) #添加auth参数,完成认证
print response.text
print response.request.headers
basic_auth()
返回数据:
{"login":"caolanmiao","id":22490616,"avatar_url":"https://avatars0.githubusercontent.com/u/22490616?v=4","gravatar_id":"","url":"https://api.github.com/users/caolanmiao","html_url":"https://github.com/caolanmiao","followers_url":"https://api.github.com/users/caolanmiao/followers","following_url":"https://api.github.com/users/caolanmiao/following{/other_user}","gists_url":"https://api.github.com/users/caolanmiao/gists{/gist_id}","starred_url":"https://api.github.com/users/caolanmiao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caolanmiao/subscriptions","organizations_url":"https://api.github.com/users/caolanmiao/orgs","repos_url":"https://api.github.com/users/caolanmiao/repos","events_url":"https://api.github.com/users/caolanmiao/events{/privacy}","received_events_url":"https://api.github.com/users/caolanmiao/received_events","type":"User","site_admin":false,"name":"Yannan.Jia","company":null,"blog":"","location":"Pecking","email":"534304558@qq.com","hireable":null,"bio":"Software QA Engineer","public_repos":1,"public_gists":0,"followers":0,"following":1,"created_at":"2016-09-28T06:00:27Z","updated_at":"2017-08-19T09:27:39Z","private_gists":0,
"total_private_repos":0,"owned_private_repos":0,"disk_usage":0,"collaborators":0,"two_factor_authentication":false,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
{'Authorization': 'Basic Y2FvbGFubWlhbzpqaWEyMjE1NDkw', 'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.18.3'}
返回的数据中,可以看到,添加auth参数后,在request的headers中加了一串Authorization,Basic后面的这一串码“Y2FvbGFubWlhbzpqaWEyMjE1NDkw”是什么呢?
其实这一串码是base64格式的,解码后就是我的用户名和密码('caolanmiao','key######')。
所以这种基本形式的认证是把用户名和密码放在request的headers中,使用任何语言(比如python)都可以对已经编码后的用户名和密码进行解码,可见,具备一定的安全性,但是安全性并不够强。
另一种安全性更强的认证---OAUTH认证
比如一个app在登录的时候,提供了通过github账号来快速登录的入口,那么完成登录的流程就如下图所示:
实验代码:
# -*- coding:utf-8 -*-
import requests
BASE_URL='https://api.github.com'
def construct_url(end_point):
return '/'.join([BASE_URL,end_point])
def basic_oauth():
headers={'Authorization':'token dd6322fa6c57a548268453dc245cbcdc352a7811'} #通过token完成认证
# user/emails
response=requests.get(construct_url('user/emails'),headers=headers)
print response.request.headers
print response.text
print response.status_code
7.Request库--Proxy(代理)
Heroku这个服务器(相当于国内的“阿里云”)对于国外的资源是可见的,比如是可以直接访问facebook的;Socks服务是一种在会话层的协议,类似于HTTP协议;
实现代码:
import requests
proxies={'http':'socks5://127.0.0.1080','https':'socks5://127.0.0.1080'} #定义代理
url='https://www.facebook.com'
response=requests.get(url,proxies=proxies,timeout=10) #添加代理
8.Request库--Session和Cookie
大家都知道http协议的请求和下一个请求之间是独立的、没有关系的。但是经常有些时候我们需要使得请求和上一个请求有关系,比如“在购物的情景中,已经登录了账户,把商品加入购物车中,不能出现发出一个新请求后,购物车中的商品清空了的情况”。
简而言之,session是存储在服务器端的,来保存登录信息;cookie是保存在浏览器中来存储的。
cookie存储的方式如图1:
cookie存储的方式缺点:1.每次发送请求都带着cookie,造成了带宽特别大,特别占用网络请求;2.cookie如果在浏览器端是明文存储的话,容易解析时,是可以伪造的,很不安全。
那么鉴于cookie存储方式的不足,session存储的方式应运而生。
session存储的方式如图2:
session存储的方式优点:1. 服务器返回的cookie-session-id相比于整个cookie是很小的,节省带宽,减少了网络传输的压力;2.服务器把session存储在数据库或者radis(内存)中,实现了本地化,相比于cookie存储方式的每次在网络中发送整个cookie更安全。
看到的同学也可以利用github上的api自己试试。
Python requests库的使用(二)的更多相关文章
- 大概看了一天python request源码。写下python requests库发送 get,post请求大概过程。
python requests库发送请求时,比如get请求,大概过程. 一.发起get请求过程:调用requests.get(url,**kwargs)-->request('get', url ...
- Python——Requests库的开发者接口
本文介绍 Python Requests 库的开发者接口,主要内容包括: 目录 一.主要接口 1. requests.request() 2. requests.head().get().post() ...
- Python:requests库、BeautifulSoup4库的基本使用(实现简单的网络爬虫)
Python:requests库.BeautifulSoup4库的基本使用(实现简单的网络爬虫) 一.requests库的基本使用 requests是python语言编写的简单易用的HTTP库,使用起 ...
- python requests库学习笔记(上)
尊重博客园原创精神,请勿转载! requests库官方使用手册地址:http://www.python-requests.org/en/master/:中文使用手册地址:http://cn.pytho ...
- 使用python requests库写接口自动化测试--记录学习过程中遇到的坑(1)
一直听说python requests库对于接口自动化测试特别合适,但由于自身代码基础薄弱,一直没有实践: 这次赶上公司项目需要,同事小伙伴们一起学习写接口自动化脚本,听起来特别给力,赶紧实践一把: ...
- Python requests库的使用(一)
requests库官方使用手册地址:http://www.python-requests.org/en/master/:中文使用手册地址:http://cn.python-requests.org/z ...
- python+requests库,接口自动化
1.requests库的使用 requests是python的一个HTTP客户端库,跟urllib,urllib2类似,那为什么要用requests而不用urllib2呢?官方文档中是这样说明的: “ ...
- Python Requests库:HTTP for Humans
Python标准库中用来处理HTTP的模块是urllib2,不过其中的API太零碎了,requests是更简单更人性化的第三方库. 用pip下载: pip install requests 或者git ...
- Python Requests库
背景 Requests is an elegant and simple HTTP library for Python, built for human beings. Requests是一个优雅简 ...
随机推荐
- SQLi-LABS Page-3 (Stacked injections) Less-38-Less-45
Less-38 堆叠注入原理简介堆叠注入简介 Stacked injections: 堆叠注入.从名词的含义就可以看到应该是一堆 sql 语句(多条)一起执行.而在真实的运用中也是这样的, 我们知道在 ...
- crawlscrapy简单使用方法
crawlscrapy简单使用方法 1.创建项目:scrapy startproject 项目名例如:scrapy startproject wxapp windows下,cmd进入项目路径例如d:\ ...
- pytroch 权重初始化和加载词向量的方法
1.几种不同的初始化方法 import torch.nn as nn embedding = torch.Tensor(3, 5) #如下6种初始化方法 #正态分布 nn.init.normal_(e ...
- 【Eureka篇三】Eureka服务注册(2)
注:修改[Rest微服务案例(二)]中的子模块microservicecloud-provider-dept-8001. 一.项目改造 1. 修改pom.xml 添加eureka client的依赖 ...
- Leetcode4__findMedianSortedArrays
findMedianSortedArrays 基本思路:通过指针按顺序移动来判断大小顺序,思路和有一道用链表求中间值一样: class Solution { public double findMed ...
- Python 链表(linked list)
链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 链表由一系列结点组成,结点可以在运行时动态生成 优点 由于不必须按顺序存储,链表在插入.删除的时候 ...
- opencv读取USB相机select timeout问题
现象: 树莓派4b或3b+ 插着两个USB免驱相机 摄像头朝着灯就会报 time out 摄像头不朝着灯就不报 问题: 功率不够 朝着灯可能触发了USB相机的曝光补偿导致功率变大 解决: 使用带额 ...
- Go micro 入门
路由跳转 官方文档 本质上是选择不同的方式将HTTP信息合理的转发至后端处理,而不同的方式相当于不同请求的接收器,接收后再将其转发至不同的后端服务,完成整个请求的调用. micro 将请求选择不同的方 ...
- luogu1368 工艺
题目链接 思路 \(SAM\)练手题,将原串重复一遍插入到\(SAM\)中,然后贪心走长度为n的一个路径即可. 不用担心会直接走到终点,根据\(SAM\)的构造方式可以发现会先走到前面的路径. 代码 ...
- Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem 背包dp
D. Yet Another Subarray Problem You are given an array \(a_1, a_2, \dots , a_n\) and two integers \( ...