内容概要
- 如何构建get 与 post request 请求消息
- 对 request 的header , query string, message body 定制化
- http header参数 content-type 的设置
- 分析request, response 消息数据
- 通过post请求向服务器上传文件,,以及从服务器接收文件
- 请求与响应使用 json 格式
为什么推荐使用 requests 模块?
用 python 编写 http request 消息代码时,建议用requests库。因为requests比urllib内置库更为简捷,requests可以直接构造get,post请求并发送,而urllib.request只能先构造get,post请求消息内容,然后再发送。并且requests 模块提供了更友好的方法与属性来解析response消息内容。
1. 准备知识
1.1 http request 与 response 通讯机制
http协议是基于1种客户机(client) – 服务器(server) 的通信模式,它的下层是tcp协议。
- 所有的请求request 都是由客户机发起的
- 服务器对客户请求做出响应response
- 每个request 都是独立于其它request消息,服务器不需要跟踪request消息的状态
1.2 http request 请求与响应消息
客户端发送一个http请求到服务器的请求消息由四个部分组成
- 请求行(request line)
- 头部(header)、
- 空行(clf)
- 报文主体(payload,或body)
下图给出了请求报文的一般格式。
上图中,可以看到。request 请求行第1个字节为请求方法
, 有时也称动词
(verb), 常用的主要有4种方法:get, post, put, delete
。
1.3 http response 响应消息
服务器的响应消息,也是由4部分组成
状态行、头部、空行和响应正文
请求消息与响应消息的头部都是由头部字段构成,它能起到传递额外重要信息的作用。 使用首部字段是为了给浏览器和服务器提供报文主体大小、所使用的语言、认证信息等内容。
头部字段的格式,如下
字段名: 字段值
如
content-type: text/html
就以上述示例来看,首部字段名为 content-type,字符串 text/html 是字段值。
另外,字段值对应单个 http 首部字段可以有多个值,如下所示。
keep-alive: timeout=15, max=100
头部字段通常也用于携带用户身份信息,如访问知名站点时,对方通常会在响应的头部添加 set-cookie字段,其中包含用户id,token等加密后的数据。此后的请求的头部也会添加cookie 字段。
2. 安装 requests 模块
安装requests 模块非常简单,
pip install requests
3. 发送 get 请求
3.1 request.get() 方法
get()方法用于准备并发送 http get 请求至指定url , 并返回response 对象
语法
requests.get(url, params=none, **kwargs)
- url: 拟获取页面的url链接
- params: url中的额外参数,字典或字节流格式,可选
**kwargs
: 可选参数.
url 完整格式
最终发送的完整url, 是将输入url 与parameters 拼接形成,格式如下:
url格式:http://host_ip:port/path/add?key1=value1&key2=value2
3.2 get 方法的请求参数 queryparameters
get方法的请求参数是通过 params来传递的。 其类型为字典,params={ key1: value1, key2: value2 }
response = requests.get( 'https://api.github.com/search/repositories', params={'name': 'jack','type':'display'}, )
requests 模块会将url与parameters 拼接成完整的请求消息
ttps://api.github.com/search/repositories?name=jack&type=display
可能遇到的问题 : 如果get请求参数中包含汉字,常会遇到编码错误
主要原因:http协议对url参数的编码要求是ascii字符集,而汉字是utf-8。在发送时要进行两次编码才能将汉字转为ascii字节码:
- 第1次编码, 用 utf-8 字符集,每个汉字占3个字节。
- 第2次编码,可以用 iso-8859-1,然后再转为ascii,也可以用其它字符集来转ascii。
同样,接收方也要进行两次解码,才能正确地还原汉字。
还好,python 内置库urllib 提供了1条命令,1次就可以将汉字转为ascii编码。
编码: urllib.parse.urlencode(dic)
解码: urllib.parse.unquote(dic or str)
示例代码
keyword = "天气预报" param_list = urllib.parse.urlencode( { 'q' : keyword } ) #包含汉字 header = {'user-agent':'haha‘} url = 'http://www.baidu.com/s/' response = request.get( url, params=param_list, headers = header )
3.3 get()方法的可选参数
get()方法的可选参数 **kwargs部分,常见的参数主要有:
- headers 设置头部参数,字典类型
- cookies 设置cookie,也是字典类型。
- auth, tupe类型,用于基本鉴权
- proxies 设置代理服务器
- stream, 为bool类型,如果请求二进制文件,图片等应设置为true
- timeout, 超时时间,为秒
headers = { 'user-agent': 'my-app/0.0.1', 'content-type': 'text/html; charset=utf-8' } response = requests.get(url, headers=headers,timeout=10)
3.4 response 对象常用属性及方法
查看响应消息内容 响应内容的文本格式:response.text
>>> r = requests.get('https://api.github.com/events') >>> r.text '[{"repository":{"open_issues":0,"url":"https://github.com/...
响应内容的二进制格式: response.content
>>>r.content b'[{"repository":{"open_issues":0,"url":"https://github.com/...
如果响应内 容是json格式,可以用response.json()方法转换成 dict类型
>>> r = requests.get('https://api.github.com/events') >>> r.json() [{'repository': {'open_issues': 0, 'url': 'https://github.com/...
分析status_code
收到response后,需要分析响应状态码status_code,有必要可以对404, 500等出错响应进行特殊处理。
import requests from requests.exceptions import httperror for url in ['https://api.github.com', 'https://api.github.com/invalid']: try: response = requests.get(url) # if the response was successful, no exception will be raised response.raise_for_status() except httperror as http_err: print(f'http error occurred: {http_err}') # python 3.6 except exception as err: print(f'other error occurred: {err}') # python 3.6 else: print('success!')
当调用 .raise_for_status()
, 对特定的status_code将产生1个 httperror
异常
status_code
收到响应状态码301重定向
如果收到的status_code 为301,可以从response.url中获取新的url.
response = requests.get("http://192.168.3.100/demo/") new_url = response.url
异常 response 消息
如果发出request后,收到异常的response, 可以用下面的数据检查 :
>>> response = requests.post('https://httpbin.org/post', json={'key':'value'}) >>> response.request.headers['content-type'] 'application/json' >>> response.request.url 'https://httpbin.org/post' >>> response.request.body b'{"key": "value"}'
或将所有头部字段打印出来:
resp = requests.get(url, headers=header) for head in resp.headers: print(head, ":", resp.headers[head])
output类似于:
date : thu, 13 jul 2023 05:00:49 gmt server : wsgiserver/0.2 cpython/3.9.4 content-type : text/html; charset=utf-8 x-frame-options : deny content-length : 3669 x-content-type-options : nosniff referrer-policy : same-origin
4. 发送 post 请求
4.1 requests.post()方法的使用
与get请求不同的是, post 请求参数是放在 request body 里发送的,
post() 语法
requests.post(url, data=none, json=none, **kwargs)
post请求参数使用data, 或json传入。data的数据类型可以是dict,tuple, list等, json也就是json。
返回类型为 response类型。
# 请求参数以字典方式坆 post_dict = {'key1': 'value1', 'key2': 'value2'} # 以元组方式传入 post_tuple = (('key1', 'value1'), ('key1', 'value2')) # 用json格式 post_json = { "some": "data" } headers = { "content-type": "application/json" } r1 = requests.post("http://httpbin.org/post", data=post_dict) r2 = requests.post("http://httpbin.org/post", data=post_tuple) r3 = requests.post("http://httpbin.org/post", json=post_json, headers=headers)
收到 response。 response对象主要属性与方法,请参考上一节内容。
http/1.1 200 ok content-length: 19 content-type: application/json {"success":"true"}
4.2 post 消息设置 cookie, header
import requests # 请求数据 url = 'http://api.shein.com/v2/member/login' cookie = "token=code_space;" header = { "cookie": cookie, "accept": "*/*", "accept-encoding": "gzip, deflate, br", "accept-language": "zh-cn,zh;q=0.9", "connection": "keep-alive", "content-type": "application/json", "user-agent": "mozilla/5.0 (windows nt 10.0; win64; x64) " "applewebkit/537.36 (khtml, like gecko) chrome/92.0.4515.159 safari/537.36" } data = { 'user_id': '123456', 'email': '123456@163.com' } timeout = 0.5 resp = requests.post(url, headers=header, data=data, timeout=timeout) print(resp.text) print(type(resp.json()))
4.3 用 post请求向服务器上传文件
客户端可通过post请求,向服务器上传文件
#形式1 url = 'http://httpbin.org/post' #定义文件对象 files = {"files":open('test.xls', 'rb')} response = requests.post(url,files = files) print(response.text) #形式2 url ='http://httpbin.org/post' files = {'file': ('t.xls', open('t.xls', 'rb'), 'application/vnd.ms-excel', {'expires': '0'})} r = requests.post(url, files=files) r.text #形式3, 发送多个文件 url = 'http://httpbin.org/post' files = {'file': ('t.csv', 'bb.csv')} response = requests.post(url, files=files) response.text
4.4 从服务器接收文件
向服务器请求1个2进制文件时,stream设置为true.
r = requests.get('https://api.github.com/events', stream=true) print(r.raw.read(10))
r.raw 是文件原始内容,可以用文件的方式读取,如 r.raw.read(10)。 如果尺寸不大,可直接保存到文件。如果收到的内容比较大,用response的 iter_content()方法来分块保存,以避免内存溢出等风险
with open(filename, 'wb') as fd: for chunk in r.iter_content(chunk_size=128): fd.write(chunk)
4.5 基本鉴权
当服务器web应用的认证采用的是基本鉴权(basic authentication) 时,使用auth参数传入username与password。 get(), post() 均支持。
from requests.auth import httpbasicauth requests.post(url, auth=httpbasicauth("username", "password"))
5、请求与响应头部的 content-type 参数说明
上一切,发送json格式请求参数时,要设置头部参数"content-type": “application/json”,
content-type 参数用于告诉服务器或浏览器,http 消息所包含资源的类型。这个参数在request 与 response消息中都可能包含,是 response 消息头部非常关键1个参数,也是开发者应该掌握的1个知识点。其内容格式是 ietf’s rfc 6838 标准中的 mime type
(multipurpose internet mail extensions).
先看1个实际消息示例 :
content-type: text/html; charset=utf-8 content-type: multipart/form-data; boundary=something
content-type 参数的语法格式:
type/subtype
- type 代表数据资源的大类,如 text (文本类型), video(视频类型)等
- subtype 是资源子类,如,对于 text类,subtype 可能是 plain(纯文本),csv 或者html等。
content-type还可以附加参数
type/subtype;parameter=value
常见情形:当type是 text类型,文本内容是中文,需添加charset参数,指定编码类型:content-type: text/html;charset=utf-8
在http协议以及行业内,有很多通用的建议值,最常见的:
application/x-www-form-urlencoded
, 这是提交表单默认的content-type设置, 对应form属性为 enctype=“application/x-www-form-urlencoded”。multipart/form-data
, 用于 form 上传文件application/json
传json数据text/html
传网页text/plain text/xml
传文本image/jpeg
传图片video/mp4
传mp4视频
等。
注:
对于"application/x-www-form-urlencoded" 编码,如果两端都是用request编程,则不需要编解码,request 模块会自动完成。
下面是 content-type 可能用到的 type/subtype 列表:
type | subtype |
---|---|
application | application/javascript application/pdf application/xhtml+xml application/json application/ld+json application/xml application/zip application/x-www-form-urlencoded application/octet-stream : 二进制流数据(如常见的文件下载) |
audio | audio/mpeg audio/x-ms-wma |audio audio/x-wav |
image | image/gif image/jpeg image/png image/tiff i mage/vnd.microsoft.icon image/x-icon image/vnd.djvu image/svg+xml |
multipart | multipart/mixed multipart/alternative multipart/related (using by mhtml (html mail).) multipart/form-data |
text | text/css text/csv text/html text/plain text/xml |
video | video/mpeg video/mp4 video/quicktime video/x-ms-wmv video/x-msvideo video/x-flv video/webm |
vnd | application/vnd.oasis.opendocument.text application/vnd.oasis.opendocument.spreadsheet application/vnd.oasis.opendocument.presentation application/vnd.oasis.opendocument.graphics application/vnd.ms-excel application/vnd.openxmlformats-officedocument.spreadsheetml.sheet application/vnd.ms-powerpoint application/vnd.openxmlformats-officedocument.presentationml.presentation application/msword application/vnd.openxmlformats-officedocument.wordprocessingml.document application/vnd.mozilla.xul+xml |
6. 用 json 做 payload
payload 就是通过http post,get发送的数据,包括请求参数,文件,图片等, 发送方可以将用json类型来准备这些数据,接收方用json解开。
这在header 里约定好。如下, 但注意,header 不能是json格式。
import json import requests url = "http://www.example.com" payload = {'data': 12345, } rep = requests.post(url, data=json.dumps(payload)) print(rep.text.json())
用 data 参数提交数据时, request.body 的内容则为 a=1&b=2 的这种形式,用 json 参数提交数据时, request.body 的内容则为’“a”: 1, “b”: 2’ 的这种形式,如
post /echo/post/json http/1.1 host: reqbin.com accept: application/json content-type: application/json content-length: 52 { "id": 12345 }
检查响应消息response头部参数’content-type’,如果为 “application/json”,表示内容为 json 格式. 可使用response对象内置方法json()查看响应消息的内容
>>> r.headers['content-type'] 'application/json; charset=utf8' >>> r.json() {"success": "true", "data": { "totalorders": 100 } }
7. 其它requests 方法
其它请求消息, put与patch与 post类似。 delete, head与get类似。
>>> requests.put('https://httpbin.org/put', data={'key':'value'}) >>> requests.delete('https://httpbin.org/delete') >>> requests.head('https://httpbin.org/get') >>> requests.patch('https://httpbin.org/patch', data={'key':'value'}) >>> requests.options('https://httpbin.org/get')
以上就是使用python requests模块发送http请求及接收响应的方法的详细内容,更多关于python requests发送http的资料请关注代码网其它相关文章!
发表评论