HTTP请求:requests的进阶使用方法浅析

http,请求,requests,进阶,使用,方法,浅析 · 浏览次数 : 396

小编点评

**requests库简介** requests库是一个第三方库,它提供与urilib2模块类似的便捷 API。使用 requests库可以轻松完成各种HTTP请求,并使其更加人性化。 **主要特点** - 支持HTTP连接保持和连接池 - 使用cookie、session保持会话 - 支持文件上传 - 自动响应内容的编码 - 支持国际化的URL和Post数据自动编码 - 支持自动实现持久连接keep-alive **使用示例** ```python import requests # 获取HTTP连接保持和连接池 response = requests.get("http://127.0.0.1:8080/example/post") # 获取文件上传 response = requests.post("http://127.0.0.1:8080/example/post", files={"example": open("example.txt", "rb")}) # 获取自动响应内容的编码 response = requests.get("http://127.0.0.1:8080/example/post", encoding="utf-8") # 获取国际化的URL和Post数据自动编码 response = requests.get("http://127.0.0.1:8080/example/post", params={"example": "123"} # 自动实现持久连接 response = requests.get("http://127.0.0.1:8080/example/post", keep_alive=True) ``` **其他** - requests库支持多种HTTP方法,包括GET、POST、PUT、DELETE、COOKIE和Session。 - 它提供了自动响应内容的编码支持,可以确保请求的响应内容是正确的编码的。 - 它支持国际化的URL和Post数据自动编码,可以完成跨国请求。

正文

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 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

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

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

设置重定向开关。

>>> 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。

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协议的代理。

# 安装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的钩子,即在响应返回时,可以捎带执行自定义方法。可以用于打印一些信息、做一些响应检查、或者向响应中添加额外的信息。

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会将报文一次性全部加载到内存中,如果报文过大,可以使用此参数,迭代下载。

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证书。

# 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

示例:

# 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

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

# 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

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

# 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”。

作者:京东物流 骆铜磊

来源:京东云开发者社区

与HTTP请求:requests的进阶使用方法浅析相似的内容:

HTTP请求:requests的进阶使用方法浅析

上篇文章讲解了requests模块的基础使用,其中有get、put、post等多种请求方式,使用data、json等格式做为请求参数,在请求体中添加请求头部信息的常见信息,如:headers、cookies,以及对请求响应的处理方法。接下来讲解一下requests的高级用法。

HTTP请求:requests模块基础使用必知必会

http请求是常见的一种网页协议,我们看到的各种网页,其实都是发送了http请求得到了服务器的响应,从而将数据库中复杂的数据以简单、直观的方式呈现出来,方便大众阅读、使用。而如何发送http请求呢?今天来探讨一下使用requests模块,达到高效、简单的http请求操作。

kettle从入门到精通 第七十一课 ETL之kettle 再谈http post,轻松掌握body中传递json参数

场景: kettle中http post步骤如何发送http请求且传递body参数? 解决方案: http post步骤中直接设置Request entity field字段即可。 1、手边没有现成的post接口,索性用python搭建一个简单的接口,关键代码如下(安装python环境略): fro

[转帖]HTTP请求错误400、401、402、403、404、405、406、407、412、414、500、501、502解析

https://www.cnblogs.com/jiangjunli/p/7639578.html HTTP 错误 400 400 请求出错 由于语法格式有误,服务器无法理解此请求。不作修改,客户程序就无法重复此请求。 HTTP 错误 401 401.1 未授权:登录失败 此错误表明传输给服务器的证

[转帖]http请求详解

1. 简介 HTTP(HyperText Transfer Protocol,超文本传输协议)是一套计算机通过网络进行通信的规则。计算机专家设计出HTTP,使HTTP客户(如Web浏览器)能够从HTTP服务器(Web服务器)请求信息和服务,HTTP目前协议的版本是1.1。HTTP遵循请求(Reque

再谈http请求调用(Post与Get),项目研发的核心一环

支持.Net Core(2.0及以上)与.Net Framework(4.0及以上) 【目录】 前言 Post请求 Get请求 与其它工具的比较 1【前言】 http请求调用是开发中经常会用到的功能。 在内,调用自有项目的Web Api等形式接口时会用到;在外,调用一些第三方功能接口时,也会用到,因

Http请求get与post请求方式的各种相关面试总结

转载请注明出处: GET方法和POST方法是两种HTTP请求方法,GET方法通过URL传递参数,可以缓存,但参数长度有限,一般用于获取资源;POST方法通过表单传递参数,不能缓存,参数长度没有限制,一般用于提交数据。 1. GET和POST方法的区别 1.数据传递方式:GET方法的参数以查询字符串方

深入解析HTTP请求:了解请求特征与报文格式的关键秘密

这篇文章将带您深入了解HTTP请求的特征和报文格式。HTTP作为一种简单、灵活且易于扩展的协议,适用于各种操作系统和设备。我们还将探讨持久性连接如何提高请求的效率。了解HTTP报文的构成,包括起始行、头部字段和消息正文,将帮助您更好地理解HTTP的工作原理。无论您是初学者还是已经有一定了解的读者,本...

【进阶篇】一文搞清楚网页发起 HTTP 请求调用的完整过程

最近笔者在实际项目开发中会频繁涉及到服务之间的远程调用、域名的配置和请求的转发等与计算机网络相关的知识。 这些其实在读本科和考研的时候都有学习过理论,但为了更透彻地掌握便于在工作中使用,我还是决定写一篇文章来分享实际开发中是怎么应用的。

[转帖]Jmeter创建简单的HTTP(S)请求测试-3

在上一章节中,介绍了Jmeter基本的组成组件,那么我们如何使用这些组件去完成测试呢,以下将通过创建一个简单的HTTP(S)测试进行说明,另外,除JDBC请求外,Jmeter进行测试构建的步骤大同小异,所以不再一一赘述。 3.1 添加线程组 每个JMeter测试计划进行的第一步是添加一个线程组。线程