您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
HTTP请求:requests使用(-进阶篇)
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
HTTP请求:requests使用(-进阶篇)
自猿其说Tech
2023-06-09
IP归属:北京
12200浏览
# 1 背景 上篇文章讲解了requests模块的基础使用,其中有get、put、post等多种请求方式,使用data、json等格式做为请求参数,在请求体中添加请求头部信息的常见信息,如:headers、cookies,以及对请求响应的处理方法。接下来讲解一下requests的高级用法。 # 2 进阶方法举例 ## 2.1 requests.request() method:提交方式(get|post); url:提交地址; **kwargs:14个控制访问的参数; ![](//img1.jcloudcs.com/developer.jdcloud.com/0a5471bb-2e89-485e-bec9-defcf4f18ac620230419172548.png) 常用的参数有:params、data、json、headers、cookies,已在上篇文章中介绍过了,感兴趣的朋友,可以到上篇文章再回顾一下。以下将讲解与示例其他参数的使用。 示例: ### 2.1.1 files 请求携带文件,如果有的请求需要上传文件,可以用它来实现。 ```python 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文件需和当前脚本在同一目录下,如果不在,可以将文件名称修改为文件路径 ```python import requests from 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 请求和响应的超时时间,在网络响应延迟或者无响应时,可以通过设置超时时间,避免等待。 ```python 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 ReadTimeout try: 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 设置重定向开关。 ```python >>> import requests >>> r = requests.get('http://github.com') >>> r.url 'https://github.com/' >>> r.status_code 200 >>> r.history [<Response [301]>] # 如果使用GET、OPTIONS、POST、PUT、PATCH或DELETE,则可以使用allow_redirects参数禁用重定向 >>> r = requests.get('http://github.com', allow_redirects=False) >>> r.status_code 301 >>> r.history [] # 用HEAD启动重定向 >>> r = requests.head('http://github.com', allow_redirects=True) >>> r.url 'https://github.com/' >>> r.history [<Response [301]>] import requests import 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代表新页面的response r2=requests.post('https://github.com/session', data=data, cookies=r1_cookie ) print(r2.status_code) # 200 print(r2.url) # 看到的是跳转后的页面 print(r2.history) # 看到的是跳转前的response print(r2.history[0].text) # 看到的是跳转前的response.text # 测试二:指定allow_redirects=False,则响应头中即便出现Location也不会跳转到新页面, # r2代表的仍然是老页面的response r2=requests.post('https://github.com/session', data=data, cookies=r1_cookie, allow_redirects=False ) print(r2.status_code) # 302 print(r2.url) # 看到的是跳转前的页面https://github.com/session print(r2.history) # [] ``` ### 2.1.4 proxies 同添加headers方法一样,代理参数是dict。 ```python import requests import re def 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 html def 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协议的代理。 ```python # 安装socks库 pip3 install "requests[socks]" # 进行代理 import requests proxies = { '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的钩子,即在响应返回时,可以捎带执行自定义方法。可以用于打印一些信息、做一些响应检查、或者向响应中添加额外的信息。 ```python import requests url = '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会将报文一次性全部加载到内存中,如果报文过大,可以使用此参数,迭代下载。 ```python import requests url="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证书。 ```python # 1、直接设置 import requests response = 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 **示例:** ```python # 1、HTTPError异常示例 import requests from requests.exceptions import HTTPError try: res = requests.post("http://127.0.0.1:8080/example/post") res.raise_for_status() # 等同于 if res.status != 200: raise HTTPError return res except HTTPError: return False ``` ### 2.2.2 ReadTimeout 该异常类型,将会捕捉到因请求/响应超时的请求。 ```python # Timeout超时异常 import requests from requests.exceptions import ReadTimeout try: res = requests.get('http://127.0.0.1:8080/example/post',timeout=0.5) print(res.status_code) return res except ReadTimeout: print('timeout') ``` ### 2.2.3 RequestException 该异常类型,将会捕捉到因无请求引起的异常请求。 ```python # RquestError异常 import requests from requests.exceptions import RequestException try: res = requests.get('http://127.0.0.1:8080/example/post') print(res.status_code) return res except RequestException: print('reqerror') ``` # 3 总结 看到这里,大家应该明白了,requests库是一个比urilib2模块更加简洁的第三方库,它具有如下的特点: - 支持HTTP连接保持和连接池 - 支持使用cookie、session保持会话 - 支持文件上传 - 支持自动响应内容的编码 - 支持国际化的URL和Post数据自动编码 - 支持自动实现持久连接keep-alive 因此,requests这个高度封装的模块,可以使我们的HTTP请求,变得更加人性化,使用它将可以轻而易举的完成浏览器请求的任何操作,充分诠释了它的口号:“HTTP for Humans”。 ------------ 自猿其说Tech-JDL京东物流技术与数据智能部 **作者:骆铜磊**
原创文章,需联系作者,授权转载
上一篇:虚拟化技术浅析第二弹之初识Kubernetes
下一篇:【ChatGPT应用篇-2】助力Beauty代码
自猿其说Tech
文章数
426
阅读量
2149963
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
自猿其说Tech
文章数
426
阅读量
2149963
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号