1 背景
上篇文章解说了requests模块的根底应用,其中有get、put、post等多种申请形式,应用data、json等格局做为申请参数,在申请体中增加申请头部信息的常见信息,如:headers、cookies,以及对申请响应的解决办法。接下来解说一下requests的高级用法。
2 进阶办法举例
2.1 requests.request()
method:提交形式(get|post);
url:提交地址;
kwargs:14个管制拜访的参数;
[]()
罕用的参数有:params、data、json、headers、cookies,已在上篇文章中介绍过了,感兴趣的敌人,能够到上篇文章再回顾一下。以下将解说与示例其余参数的应用。
示例:
2.1.1 files
申请携带文件,如果有的申请须要上传文件,能够用它来实现。
import requests# 上传文件f= {"files": open("favicon.ico", "rb") }data = {"name": "上传文件"}requests.request( method = 'POST', url = 'http://127.0.0.1:8080/example/request', data = data, files = f)
需注意:favicon.ico文件需和以后脚本在同一目录下,如果不在,能够将文件名称批改为文件门路
import requestsfrom requests.auth import HTTPBasicAuth, HTTPDigestAuth# 1、Basic Auth认证res = requests.request( method = 'GET', url = 'http://127.0.0.1:8080/example/request', auth = HTTPBasicAuth("username", "password"))res.encoding = "gbk"print(res.status) # 200# 2、DIGEST 认证res = requests.request( method = 'GET', url = 'http://127.0.0.1:8080/example/request', auth = HTTPDigestAuth("username", "password"))res.encoding = "gbk"print(res.status) # 200
http auth认证的两种形式,别离为Basic形式和Digest认证,其中:Basic Auth的长处是提供简略的用户验证性能,其认证过程简单明了,适宜于对安全性要求不高的零碎或设施中;同样存在毛病:输出的用户名,明码 base64编码后会呈现在Authorization里,很容易被解析进去。
那么Digest比照Basic认证有什么不同呢?
- Digest思维,是应用一种随机数字符串,单方约定好对哪些信息进行哈希运算,即可实现单方身份的验证。Digest模式防止了明码在网络上明文传输,进步了安全性,但它仍然存在毛病,例如认证报文被攻击者拦挡到攻击者能够获取到资源。
- DIGEST 认证提供了高于 BASIC 认证的安全等级,然而和 HTTPS 的客户端认证相比仍旧很弱。
- DIGEST 认证提供避免明码被窃听的爱护机制,但并不存在避免用户假装的爱护机制。
- DIGEST 认证和 BASIC 认证一样,应用上不那么便捷灵便,且仍达不到少数 Web 网站对高度安全等级的谋求规范。因而它的适用范围也有所受限。
2.1.2 timeout
申请和响应的超时工夫,在网络响应提早或者无响应时,能够通过设置超时工夫,防止期待。
import requests# 设置申请超时1秒,1秒后无响应,将抛出异样,1秒为connect和read工夫总和requests.request( method = 'POST', url = 'http://127.0.0.1:8080/example/request', json = {'k1' : 'v1', 'k2' : 'v2'}, timeout = 1)# 别离设置connect和read的超时工夫,传入一个数组requests.request( method = 'POST', url = 'http://127.0.0.1:8080/example/request', json = {'k1' : 'v1', 'k2' : 'v2'}, timeout = (5, 15))# 永恒期待requests.request( method = 'POST', url = 'http://127.0.0.1:8080/example/request', json = {'k1' : 'v1', 'k2' : 'v2'}, timeout = None # 或者删除timeout参数)# 捕获超时异样from requests.exceptions import ReadTimeouttry: res = requests.get('http://127.0.0.1:8080/example/request', timeout=0.1) print(res.status_code)except ReadTimeout: print("捕捉到超时异样")
2.1.3 allow_redirects
设置重定向开关。
>>> import requests>>> r = requests.get('http://github.com')>>> r.url'https://github.com/'>>> r.status_code200>>> r.history[<Response [301]>]# 如果应用GET、OPTIONS、POST、PUT、PATCH或DELETE,则能够应用allow_redirects参数禁用重定向>>> r = requests.get('http://github.com', allow_redirects=False)>>> r.status_code301>>> r.history[]# 用HEAD启动重定向>>> r = requests.head('http://github.com', allow_redirects=True)>>> r.url'https://github.com/'>>> r.history[<Response [301]>]import requestsimport re# 第一次申请r1=requests.get('https://github.com/login')r1_cookie=r1.cookies.get_dict() #拿到初始cookie(未被受权)authenticity_token=re.findall(r'name="authenticity_token".*?value="(.*?)"',r1.text)[0] #从页面中拿到CSRF TOKEN# 第二次申请:带着初始cookie和TOKEN发送POST申请给登录页面,带上账号密码data={ 'commit':'Sign in', 'utf8':'✓', 'authenticity_token':authenticity_token, 'login':'xxxxxx@qq.com', 'password':'password'}# 测试一:没有指定allow_redirects=False,则响应头中呈现Location就跳转到新页面,# r2代表新页面的responser2=requests.post('https://github.com/session', data=data, cookies=r1_cookie )print(r2.status_code) # 200print(r2.url) # 看到的是跳转后的页面print(r2.history) # 看到的是跳转前的responseprint(r2.history[0].text) # 看到的是跳转前的response.text# 测试二:指定allow_redirects=False,则响应头中即使呈现Location也不会跳转到新页面,# r2代表的依然是老页面的responser2=requests.post('https://github.com/session', data=data, cookies=r1_cookie, allow_redirects=False )print(r2.status_code) # 302print(r2.url) # 看到的是跳转前的页面https://github.com/sessionprint(r2.history) # []
2.1.4 proxies
同增加headers办法一样,代理参数是dict。
import requestsimport redef get_html(url): proxy = { 'http': '120.25.253.234:812', 'https' '163.125.222.244:8123' } heads = {} heads['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0' req = requests.get(url, headers=heads,proxies=proxy) html = req.text return htmldef get_ipport(html): regex = r'<td data-title="IP">(.+)</td>' iplist = re.findall(regex, html) regex2 = '<td data-title="PORT">(.+)</td>' portlist = re.findall(regex2, html) regex3 = r'<td data-title="类型">(.+)</td>' typelist = re.findall(regex3, html) sumray = [] for i in iplist: for p in portlist: for t in typelist: pass pass a = t+','+i + ':' + p sumray.append(a) print('代理') print(sumray)if __name__ == '__main__': url = 'http://www.baidu.com' get_ipport(get_html(url))
某些接口减少了防骚扰模式,对于大规模且频繁的申请,可能会弹出验证码,或者跳转到登录验证页面,或者封禁IP地址,此时如果想要失常拜访,能够通过设置代理来解决这个问题。
除了根本的HTTP代理外,requests还反对SOCKS协定的代理。
# 装置socks库pip3 install "requests[socks]"# 进行代理import requestsproxies = { 'http': 'socks5://user:password@host:port', 'https': 'socks5://user:password@host:port'}res = requests.get('http://www.baidu.com', proxies=proxies)print(res.status) # 200
2.1.5 hooks
即钩子办法,requests库只反对一个response的钩子,即在响应返回时,能够捎带执行自定义办法。能够用于打印一些信息、做一些响应查看、或者向响应中增加额定的信息。
import requestsurl = 'http://www.baidu.com'def verify_res(res, *args, **kwargs): print('url', res.url) res.status='PASS' if res.status_code == 200 else 'FAIL'res = requests.get(url, hooks={'response': verify_res})print(res.text) # <!DOCTYPE html><!--STATUS OK--><html> print(res.status) # PASS
2.1.6 stream
获取内容立刻下载开关,response会将报文一次性全副加载到内存中,如果报文过大,能够应用此参数,迭代下载。
import requestsurl="http://www.baidu.com"r = requests.get(url, stream=True)# 解析response_body,以\n宰割for lines in r.iter_lines(): print("lines:", lines)# 解析response_body,以字节宰割for chunk in r.iter_content(chunk_size=1024): print("chunk:", chunk)
2.1.7 verify
认证SSL证书开关,当发送HTTPS申请的时候,如果该网站的证书没有被CA机构信赖,程序将报错,能够应用verify参数管制是否查看SSL证书。
# 1、间接设置import requestsresponse = requests.get('https://www.12306.cn', verify=False)print(response.status_code)# 2、申请时尽管设置了跳过查看,然而程序运行时依然会产生正告,正告中蕴含倡议给咱们的指定证书# 能够通过设置,疏忽屏蔽这个正告from requests.packages import urllib3 # 如果报错,则间接引入import urllib3# 3、屏蔽正告urllib3.disable_warnings()response = requests.get('https://www.12306.cn', verify=False)print(response.status_code) # 200# 4、通过cert间接申明证书# 本地须要有crt和key文件(key必须是解密状态,加密状态的key是不反对的),并指定它们的门路,response = requests.get('https://www.12306.cn',cert('/path/server.crt','/path/key'))print(response.status_code) # 200
2.2 requests库的异样
如何判断是否出现异常呢?
2.2.1 raise_for_status()
该办法在外部判断res.status_code是否等于200,不是则产生异样HTTPError
示例:
# 1、HTTPError异样示例import requestsfrom requests.exceptions import HTTPErrortry: res = requests.post("http://127.0.0.1:8080/example/post") res.raise_for_status() # 等同于 if res.status != 200: raise HTTPError return resexcept HTTPError: return False
2.2.2 ReadTimeout
该异样类型,将会捕捉到因申请/响应超时的申请。
# Timeout超时异样import requestsfrom requests.exceptions import ReadTimeouttry: res = requests.get('http://127.0.0.1:8080/example/post',timeout=0.5) print(res.status_code) return resexcept ReadTimeout: print('timeout')
2.2.3 RequestException
该异样类型,将会捕捉到因无申请引起的异样申请。
# RquestError异样import requestsfrom requests.exceptions import RequestExceptiontry: res = requests.get('http://127.0.0.1:8080/example/post') print(res.status_code) return resexcept RequestException: print('reqerror')
3 总结
看到这里,大家应该明确了,requests库是一个比urilib2模块更加简洁的第三方库,它具备如下的特点:
- 反对HTTP连贯放弃和连接池
- 反对应用cookie、session放弃会话
- 反对文件上传
- 反对主动响应内容的编码
- 反对国际化的URL和Post数据自动编码
- 反对主动实现长久连贯keep-alive
因而,requests这个高度封装的模块,能够使咱们的HTTP申请,变得更加人性化,应用它将能够轻而易举的实现浏览器申请的任何操作,充沛诠释了它的口号:“HTTP for Humans”。
作者:京东物流 骆铜磊
起源:京东云开发者社区