HTTP请求:requests的进阶使用方法浅析 | 京东云技术团队

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

请求携带文件,如果有的请求需要上传文件,可以用它来实现。

1import requests 2 3# 上传文件 4f= {"files": open("favicon.ico", "rb") } 5data = {"name": "上传文件"} 6 7requests.request( 8 method = 'POST', 9 url = 'http://127.0.0.1:8080/example/request', 10 data = data, 11 files = f 12)

需注意:favicon.ico文件需和当前脚本在同一目录下,如果不在,可以将文件名称修改为文件路径

1import requests 2from requests.auth import HTTPBasicAuth, HTTPDigestAuth 3 4# 1、Basic Auth认证 5res = requests.request( 6 method = 'GET', 7 url = 'http://127.0.0.1:8080/example/request', 8 auth = HTTPBasicAuth("username", "password") 9) 10res.encoding = "gbk" 11 12print(res.status) # 200 13 14 15# 2DIGEST 认证 16res = requests.request( 17 method = 'GET', 18 url = 'http://127.0.0.1:8080/example/request', 19 auth = HTTPDigestAuth("username", "password") 20) 21res.encoding = "gbk" 22 23print(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

请求和响应的超时时间,在网络响应延迟或者无响应时,可以通过设置超时时间,避免等待。

1import requests 2 3# 设置请求超时1秒,1秒后无响应,将抛出异常,1秒为connect和read时间总和 4requests.request( 5 method = 'POST', 6 url = 'http://127.0.0.1:8080/example/request', 7 json = {'k1' : 'v1', 'k2' : 'v2'}, 8 timeout = 1 9) 10 11# 分别设置connect和read的超时时间,传入一个数组 12requests.request( 13 method = 'POST', 14 url = 'http://127.0.0.1:8080/example/request', 15 json = {'k1' : 'v1', 'k2' : 'v2'}, 16 timeout = (5, 15) 17) 18 19# 永久等待 20requests.request( 21 method = 'POST', 22 url = 'http://127.0.0.1:8080/example/request', 23 json = {'k1' : 'v1', 'k2' : 'v2'}, 24 timeout = None 25 # 或者删除timeout参数 26) 27 28# 捕捉超时异常 29from requests.exceptions import ReadTimeout 30try: 31 res = requests.get('http://127.0.0.1:8080/example/request', timeout=0.1) 32 print(res.status_code) 33except ReadTimeout: 34 print("捕捉到超时异常")

2.1.3 allow_redirects

设置重定向开关。

1>>> import requests 2>>> r = requests.get('http://github.com') 3>>> r.url 4'https://github.com/' 5 6>>> r.status_code 7200 8 9>>> r.history 10[<Response [301]>] 11 12# 如果使用GETOPTIONSPOSTPUTPATCHDELETE,则可以使用allow_redirects参数禁用重定向 13>>> r = requests.get('http://github.com', allow_redirects=False) 14 15>>> r.status_code 16301 17 18>>> r.history 19[] 20 21# 用HEAD启动重定向 22>>> r = requests.head('http://github.com', allow_redirects=True) 23 24>>> r.url 25'https://github.com/' 26 27>>> r.history 28[<Response [301]>] 29 30 31import requests 32import re 33 34# 第一次请求 35r1=requests.get('https://github.com/login') 36r1_cookie=r1.cookies.get_dict() #拿到初始cookie(未被授权) 37authenticity_token=re.findall(r'name="authenticity_token".*?value="(.*?)"',r1.text)[0] #从页面中拿到CSRF TOKEN 38 39# 第二次请求:带着初始cookie和TOKEN发送POST请求给登录页面,带上账号密码 40data={ 41 'commit':'Sign in', 42 'utf8':'✓', 43 'authenticity_token':authenticity_token, 44 'login':'xxxxxx@qq.com', 45 'password':'password' 46} 47 48 49# 测试一:没有指定allow_redirects=False,则响应头中出现Location就跳转到新页面, 50# r2代表新页面的response 51r2=requests.post('https://github.com/session', 52 data=data, 53 cookies=r1_cookie 54 ) 55 56print(r2.status_code) # 200 57print(r2.url) # 看到的是跳转后的页面 58print(r2.history) # 看到的是跳转前的response 59print(r2.history[0].text) # 看到的是跳转前的response.text 60 61# 测试二:指定allow_redirects=False,则响应头中即便出现Location也不会跳转到新页面, 62# r2代表的仍然是老页面的response 63r2=requests.post('https://github.com/session', 64 data=data, 65 cookies=r1_cookie, 66 allow_redirects=False 67 ) 68 69print(r2.status_code) # 302 70print(r2.url) # 看到的是跳转前的页面https://github.com/session 71print(r2.history) # []

2.1.4 proxies

同添加headers方法一样,代理参数是dict。

1import requests 2import re 3def get_html(url): 4 proxy = { 5 'http': '120.25.253.234:812', 6 'https' '163.125.222.244:8123' 7 } 8 heads = {} 9 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' 10 req = requests.get(url, headers=heads,proxies=proxy) 11 html = req.text 12 return html 13def get_ipport(html): 14 regex = r'<td data-title="IP">(.+)</td>' 15 iplist = re.findall(regex, html) 16 regex2 = '<td data-title="PORT">(.+)</td>' 17 portlist = re.findall(regex2, html) 18 regex3 = r'<td data-title="类型">(.+)</td>' 19 typelist = re.findall(regex3, html) 20 sumray = [] 21 for i in iplist: 22 for p in portlist: 23 for t in typelist: 24 pass 25 pass 26 a = t+','+i + ':' + p 27 sumray.append(a) 28 print('代理') 29 print(sumray) 30if __name__ == '__main__': 31 url = 'http://www.baidu.com' 32 get_ipport(get_html(url))

某些接口增加了防骚扰模式,对于大规模且频繁的请求,可能会弹出验证码,或者跳转到登录验证页面,或者封禁IP地址,此时如果想要正常访问,可以通过设置代理来解决这个问题。
除了基本的HTTP代理外,requests还支持SOCKS协议的代理。

1# 安装socks库 2pip3 install "requests[socks]" 3 4# 进行代理 5import requests 6 7proxies = { 8 'http': 'socks5://user:password@host:port', 9 'https': 'socks5://user:password@host:port' 10} 11res = requests.get('http://www.baidu.com', proxies=proxies) 12print(res.status) # 200

2.1.5 hooks

即钩子方法,requests库只支持一个response的钩子,即在响应返回时,可以捎带执行自定义方法。可以用于打印一些信息、做一些响应检查、或者向响应中添加额外的信息。

1import requests 2url = 'http://www.baidu.com' 3 4def verify_res(res, *args, **kwargs): 5 print('url', res.url) 6 res.status='PASS' if res.status_code == 200 else 'FAIL' 7 8res = requests.get(url, hooks={'response': verify_res}) 9print(res.text) # <!DOCTYPE html><!--STATUS OK--><html> 10print(res.status) # PASS

2.1.6 stream

获取内容立即下载开关,response会将报文一次性全部加载到内存中,如果报文过大,可以使用此参数,迭代下载。

1import requests 2 3url="http://www.baidu.com" 4 5r = requests.get(url, stream=True) 6 7# 解析response_body,以\n分割 8for lines in r.iter_lines(): 9 print("lines:", lines) 10 11# 解析response_body,以字节分割 12for chunk in r.iter_content(chunk_size=1024): 13 print("chunk:", chunk)

2.1.7 verify

认证SSL证书开关,当发送HTTPS请求的时候,如果该网站的证书没有被CA机构信任,程序将报错,可以使用verify参数控制是否检查SSL证书。

1# 1、直接设置 2import requests 3 4response = requests.get('https://www.12306.cn', verify=False) 5print(response.status_code) 6 7# 2、请求时虽然设置了跳过检查,但是程序运行时仍然会产生警告,警告中包含建议给我们的指定证书 8# 可以通过设置,忽略屏蔽这个警告 9from requests.packages import urllib3 # 如果报错,则直接引入import urllib3 10 11# 3、屏蔽警告 12urllib3.disable_warnings() 13 14response = requests.get('https://www.12306.cn', verify=False) 15print(response.status_code) # 200 16 17# 4、通过cert直接声明证书 18# 本地需要有crt和key文件(key必须是解密状态,加密状态的key是不支持的),并指定它们的路径, 19response = requests.get('https://www.12306.cn',cert('/path/server.crt','/path/key')) 20print(response.status_code) # 200

2.2 requests库的异常

如何判断是否出现异常呢?

2.2.1 raise_for_status()

该方法在内部判断res.status_code是否等于200,不是则产生异常HTTPError

示例:

1# 1HTTPError异常示例 2import requests 3from requests.exceptions import HTTPError 4 5try: 6 res = requests.post("http://127.0.0.1:8080/example/post") 7 res.raise_for_status() 8 # 等同于 9 if res.status != 200: 10 raise HTTPError 11 12 return res 13 14except HTTPError: 15 return False

2.2.2 ReadTimeout

该异常类型,将会捕捉到因请求/响应超时的请求。

1# Timeout超时异常 2import requests 3from requests.exceptions import ReadTimeout 4 5try: 6 res = requests.get('http://127.0.0.1:8080/example/post',timeout=0.5) 7 print(res.status_code) 8 return res 9 10except ReadTimeout: 11 print('timeout')

2.2.3 RequestException

该异常类型,将会捕捉到因无请求引起的异常请求。

1# RquestError异常 2import requests 3from requests.exceptions import RequestException 4 5try: 6 res = requests.get('http://127.0.0.1:8080/example/post') 7 print(res.status_code) 8 return res 9 10except RequestException: 11 print('reqerror')

3 总结

看到这里,大家应该明白了,requests库是一个比urilib2模块更加简洁的第三方库,它具有如下的特点:

  • 支持HTTP连接保持和连接池
  • 支持使用cookie、session保持会话
  • 支持文件上传
  • 支持自动响应内容的编码
  • 支持国际化的URL和Post数据自动编码
  • 支持自动实现持久连接keep-alive

因此,requests这个高度封装的模块,可以使我们的HTTP请求,变得更加人性化,使用它将可以轻而易举的完成浏览器请求的任何操作,充分诠释了它的口号:“HTTP for Humans”。

作者:京东物流 骆铜磊

来源:京东云开发者社区

点赞
收藏

评论区

加载中...

相关推荐

太强了,用Python+Excel制作天气预报表!

大家好,我是小F~今天给大家介绍一个PythonExcel的实战项目,非常有趣。主要使用xlwings和requests这两个Python库,以及Office的Excel。xlwings处理表格,requests则是请求数据。先从Excel中获取城市信息,然后请求接口,获取到天气信息,再返回给Excel。具体操作可以看下图~

python的requests模块的使用

前言:在web后台开发过程中,会遇到需要向第三方发送http请求的场景,python中的requests库可以很好的满足这一要求,这里简要记录一下requests模块的使用!说明:这里主要记录一下requests模块的如下几点:1.requests模块的安装2.requests模块发送get请求3.requests模块

Linux模拟HTTP请求

一个简单的GET请求使用curl命令可以轻松发起一个HTTP请求:使用GET凡是请求网址curlhttp://www.baidu.com可以使用X选项指定请求方式携带参数的POST请求下面演示一个带头部和参数的POST请求curlXPOST\'http://u

Prometheus监控学习笔记之PromQL简单示例

0x00简单的时间序列选择返回度量指标http_requests_total的所有时间序列样本数据:http_requests_total返回度量指标名称为http_requests_total,标签分别是job"apiserver",handler"/api/comments"

ES[7.6.x]学习笔记(三)新建索引

与ES的交互方式与es的交互方式采用http的请求方式,请求的格式如下:curlX<VERB'<PROTOCOL://<HOST:<PORT/<PATH?<QUERY_STRING'd'<BODY'<VERB是请求的方法,比如:GET、POST、DELETE、PUT等。

Python实训第三天

1.requests基本使用importrequests导入requests请求库往百度主页发送请求,获取响应对象responserequests.get(url'https://www.baidu.com/')设置字符编码为utf8response.enco

HTTP请求:requests的进阶使用方法浅析 | 京东云技术团队 - HelloWorld