1.3Requests
Requests 基本使用
python发送请求时,可以用requests模块,这个模块不是内置模块
需要安装pip install requests
Requests库的七个主要方法:
方法 | 描述 |
---|---|
requests.request() | 构造一个请求,支撑一下各方法的基础方法 |
requests.get() | 获取HTML网页的主要方法,对应HTTP的GET |
requests.head() | 获取HTML网页头的信息方法,对应HTTP的HEAD |
requests.post() | 向HTML网页提交POST请求方法,对应HTTP的POST |
requests.put() | 向HTML网页提交PUT请求的方法,对应HTTP的RUT |
requests.patch() | 向HTML网页提交局部修改请求,对应于HTTP的PATCH |
requests.delete() | 向HTML页面提交删除请求,对应HTTP的DELETE |
get() 方法
requests.get(url, params=None, **kwargs)
url : 拟获取页面的url链接
params : url中的额外参数,字典或字节流格式,可选
**kwargs:控制访问参数,共12个
带参数
方式一
ret = requests.get("http://httpbin.org/get?name=leti&age=23")
方式二(建议使用,中文会自动转码)
ret=requests.get('http://0.0.0.0:8001/',params={'name':"美女",'age':18}) print(ret.text)
headers
ret = requests.get('http://0.0.0.0:8001/?name=%E7%BE%8E%E5%A5%B3', headers={ # 标志,什么东西发出的请求,浏览器信息,django框架,从哪取?(meta) 'User-Agent': 'request', # 上一个页面的地址,图片防盗链 'Referer': 'xxx' }) print(ret)
图片防盗链:如果图片的referer不是我自己的网站,就直接禁止掉
cookie
带 cookie,随机字符串(用户信息:也代表session),不管后台用的 token 认证,还是 session认证
第一种方式
ret = requests.get('http://0.0.0.0:8001/?name=%E7%BE%8E%E5%A5%B3', headers={ 'cookie': 'key3=value;key2=value', })
第二种方式
ret = requests.get('http://0.0.0.0:8001/?name=%E7%BE%8E%E5%A5%B3', cookies={"islogin":"xxx"})
发送 post 请求
post 请求(注册,登陆)携带数据(body)
data: urlencoded 编码ret=requests.post('http://0.0.0.0:8001/',data={'name':"kai",'age':18})
json: json 编码
import json data=json.dumps({'name':"kai",'age':18}) ret=requests.post('http://0.0.0.0:8001/',json=data)
注意:编码格式是请求头中带的,所以我可以手动修改,在 headers 中改
session 对象
session=requests.session() #跟 requests.get/post 用起来完全一样,但是它处理了 cookie #假设是一个登陆,并且成功 session.post() #再向该网站发请求,就是登陆状态,不需要手动携带 cookie session.get("地址")
Requests 对象的属性
属性 | 描述 |
---|---|
r.status_code | HTTP请求的返回状态,200表示成功 |
r.text | HTTP响应内容的字符串形式,即:url对应的页面内容 |
r.encoding | 从HTTP header中猜测的响应内容编码方式 |
r.apparent_encoding | 从内容中分析出的响应内容编码方式(备选编码方式) |
r.content | HTTP响应内容的二进制形式 |
r.url | 当次请求的地址 |
r.headers | 响应头 |
r.cookies | 服务端返回的 cookie |
r.cookies.get_dict() | 转成字典 |
r.history | 如果有重定向,放到一个列表中 |
response.iter_content() # 视频,图片迭代取值
with open("a.mp4",'wb') as f: for line in response.iter_content(): f.write(line)
乱码问题
import requests response = requests.get("https://www.baidu.com") print(response.status_code) # 打印状态码 print(response.text) #打印文本 print(response.cookies) # 打印cookie信息 print(response.content) #以字节流形式打印 print(response.content.decode("utf-8"))
我们可以看出 response 使用起来确实非常方便,这里有个问题需要注意一下: 很多情况下的网站如果直接 response.text 会出现乱码的问题,所以这个使用 response.content 这样返回的数据格式其实是二进制格式,然后通过 decode() 转换为 utf-8,这样就解决了通过 response.text 直接返回显示乱码的问题。
decode 的作用是将二进制数据解码成 unicode 编码,如 str1.decode('utf-8'),表示将 utf-8 的编码字符串解码成unicode编码。
简单的来说:decode就是把二进制数据(bytes)转化成人看的懂得英文或者汉字(decode用的比较多)
encode 的作用是将 unicode 编码的字符串编码成二进制数据,如str2.encode('utf-8'),表示将unicode 编码的字符串编码成 utf-8
请求发出后,Requests 会基于 HTTP 头部对响应的编码作出有根据的推测。当你访问 response.text 之时,Requests 会使用其推测的文本编码。你可以找出 Requests 使用了什么编码,并且能够使用 response.encoding 属性来改变它。如:response =requests.get("http://www.baidu.com") response.encoding="utf-8"
response.apparent_encoding #当前页面的编码
r = res.apparent_encoding
不管是通过response.content.decode("utf-8)的方式还是通过response.encoding="utf-8"的方式都可以避免乱码的问题发生
解析 json
返回数据,有可能是 json 格式,有可能是 html 格式
> import requests > import json > response = requests.get("http://httpbin.org/get") > print(type(response.text)) > print(response.json()) > print(json.loads(response.text)) > print(type(response.json()))
从结果可以看出 requests 里面集成的 json 其实就是执行了 json.loads() 方法,两者的结果是一样的
使用代理
正向代理
django 如何拿到客户端 ip 地址 META.get("REMOTE_ADDR")
使用代理有什么用ret=requests.get('http://0.0.0.0:8001/',proxies={'http':'地址'}) print(ret.text)
import requests ret=requests.get('https://www.cnblogs.com/',proxies={'http':'222.85.28.130:40505'})
http 请求头中:X-Forwarded-For:代理的过程
Post 上传文件
爬虫用的比较少,后台写服务
file={'myfile':open("1.txt",'rb')} ret=requests.post('http://0.0.0.0:8001/',files=file) print(ret.content)
上传图片
后端给出接口,上传阿里云后拿到阿里云图片链接
def post_img(self, img_name):
'''
图片上传阿里云
:param img_name: 上传图片的路劲/名称
:return: 图片链接
'''
url = 'http://xxx.xxx.xxx.xxx/upload'
img_file = {'file': (img_name, open(img_name, 'rb'), 'image/jpg')}
resp = requests.post(url, files=img_file).json()
img_map_link = resp['data']['url']
result_post = resp['succeeded']
return img_map_link
Form Data
AJAX Post请求中常用的两种传参数的形式:form data 和 request payload
get请求的时候,我们的参数直接反映在url里面,形式为key1=value1&key2=value2形式,比如:
http://news.baidu.com/ns?word=NBA&tn=news&from=news&cl=2&rn=20&ct=1
如果是post请求,那么表单参数是在请求体中,也是以key1=value1&key2=value2的形式在请求体中
这里要注意post请求的Content-Type为application/x-www-form-urlencoded(默认的),参数是在请求体中,即上面请求中的Form Data
Request payload
如果使用原生AJAX POST请求的话,请求的 Content-Type为application/json;charset=UTF-8
,而请求表单参数在Request Payload中
上传 payload 数据格式请求
注意: payload 数据要带上 []
def payload(self):
return [{
'accountId': "66666777",
'accountName': "黑兔",
}]
def post_payload_data(self):
import json
resp = requests.post(url, data=json.dumps(self.payload(), ensure_ascii=False).encode(), headers=self.headers, verify=False)
print(resp)
<Response [200]>
Request Payload 表示 http 请求中的有效载荷,就是 post 或 put 请求中所发送的数据内容,是 http 请求 headers 后的一部分,也就是请求体。
值 | 描述 |
---|---|
application/x-www-form-urlencoded | 在发送前编码所有字符(默认) |
multipart/form-data | 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。 |
text/plain | 空格转换为 "+" 加号,但不对特殊字符编码。 |
application/json | 消息主体是序列化后的 JSON 字符串 |