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

33次阅读

共计 6917 个字符,预计需要花费 18 分钟才能阅读完成。

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

作者:京东物流 骆铜磊

起源:京东云开发者社区

正文完
 0