requests
requests库是Python语言编写,基于urllib,采用Apache2 Licensed开源协议的HTTP库。
安装
pip install requests pip install -i https://pypi.doubanio.com/simple/ requests
使用之前需引入。
测试安装是否成功
import requests # 回车不报错就算安装成功 response = requests.get("https://www.baidu.com") print(response.status_code) # 200
有网的情况下,返回了200表示安装成功。
requests库的主要方法
方法 | 描述 |
---|---|
requests.request() | 构造一个请求,支持以下各种方法 |
requests.get() | 获取html的主要方法 |
requests.head() | 获取html头部信息的主要方法 |
requests.post() | 向html网页提交post请求的方法 |
requests.put() | 向html网页提交put请求的方法 |
requests.patch() | 向html提交局部修改的请求 |
requests.delete() | 向html提交删除请求 |
requests.Session() | session相关 |
我们一起来看看都是怎么玩儿的。
requests.request()
这一节非常的重要!!!能用到的参数、基本都在这节展开。
请求接受的参数
requests.request(method, url, **kwargs)类能够构造一个请求,支持不同的请求方式。
import requests response = requests.request(method='get', url='https://www.baidu.com') print(response.status_code)
request类中来看看几个参数:
- method:请求方式。
- url:请求URL。
- **kwargs:
- params:字典或者字节序列,作为参数增加到url中,使用这个参数可以把一些键值对以
k1=v1&k2=v2
的模式增加到url中,get请求中用的较多。 - data:字典、字节序列或者文件对象,重点作为向服务器提供或提交资源,作为请求的请求体,与params不同放在url上不同。它也可以接受一个字符串对象。
- json:json格式的数据,可以向服务器提交json类型的数据。
- headers:字典,定义请求的请求头,比如可以headers字典定义user agent。
- cookies:字典或者CookieJar。
- auth:元组,用来支持HTTP认证功能。
- files:字典,用来向服务器传输文件。
- timeout:指定超时时间。
- proxies:字典,设置代理服务器。
- allow_redirects:开关,是否允许对URL进行重定向,默认为True。
- stream:开关,是否对获取内容进行立即下载,默认为False,也就是立即下载。这里需要说明的,stream一般应用于流式请求,比如说下载大文件,不可能一次请求就把整个文件都下载了,不现实,这种情况下,就要设置
stream=True
,requests无法将连接释放回连接池,除非下载完了所有数据,或者调用了response.close。 - verify:开关,用于SSL证书认证,默认为True。
- cert:用于设置保存本地SSL证书路径。
- params:字典或者字节序列,作为参数增加到url中,使用这个参数可以把一些键值对以
流式请求,指的不是请求是流,而是请求返回的数据流,返回一点取一点,而普通的请求是返回完毕你再取内容。
响应对象支持的属性
import requests response = requests.request(method='get', url='http://www.httpbin.org/get')
当一个请求被发送后,会有一个response响应。requests同样为这个response赋予了相关方法:
- response:响应对象。
- response.status_code:请求返回状态码。
- response.text:字符串形式的响应内容。
- response.json():返回响应的是json类型的数据,如果响应的类型不是json,则抛出
ValueError
。 - response.content:二进制的响应内容。
- response.iter_content(chunk_size):生成器,在
stream=True
的情况下,当遍历生成器时,以块的形式返回,也就是一块一块的遍历要下载的内容。避免了遇到大文件一次性的将内容读取到内存中的弊端,如果stream=False
,全部数据作为一个块返回。chunk_size参数指定块大小。 - response.iter_lines():生成器,当
stream=True
时,迭代响应数据,每次一行,也就是一行一行的遍历要下载的内容。同样避免了大文件一次性写入到内存中的问题。当然,该方法不安全。至于为啥不安全,咱也不知道,咱也不敢问,主要是官网上没说!经查,如果多次调用该方法,iter_lines不保证重新进入时的安全性,因此可能会导致部分收到的数据丢失。 - response.cookies:响应中的cookie信息。
- response.cookies.get_dict():以字典的形式返回cookies信息。
- response.cookies.items():以列表的形式返回cookies信息。
- response.headers:响应头字典。取其中的指定key,响应头包含Content-Type,根据它的类型,采用相对应的取值方法(json,text,content)
response.headers.get('Content-Type', '哎呀,没取到!')
- response.reqeust:请求类型。
- response.url:请求的URL。常用的场景图片名字切割,response.url.split('/')
- response.reason:响应HTTP状态的文本原因。
- response.encoding:响应结果的编码方式,使用场景一般拿到的返回结果是乱码,可用尝试使用修改编码的方式来查看
- response.encoding = “gbk”:修该响应编码方式,比如说响应结果的编码是utf-8,通过这么
response.encoding = “gbk”
指定为gbk。 - response.apparent_encoding:根据响应字节流中去chardet库中匹配,返回编码方式,并不保证100%准确。
- response.history:以列表的形式返回请求记录。列表内的请求以最老到最新排序。
requests.get()
requests.get(url, params=None, **kwargs)
发送GET
请求。相关参数:
- url,请求的URL。
- params参数: 可选url中的额外参数,字典或者字节流格式。
- **kwargs:参见requests.request中的kwargs。
params参数
get请求难免会带一些额外的参数K1=V1&K2=V2
。
我们可以手动的拼接:
import requests response = requests.get(url='http://www.httpbin.org/get?k1=v1&k2=v2') print(response.url) # http://www.httpbin.org/get?k1=v1&k2=v2 print(response.json().get('args')) # {'k1': 'v1', 'k2': 'v2'}
虽然没问题,但是稍显麻烦。
现在,我们可以使用params参数来解决这个问题。
import requests params = {"user": "张开", "pwd": "666"} response = requests.get(url='http://www.httpbin.org/get', params=params) print(response.url) # http://www.httpbin.org/get?user=%E5%BC%A0%E5%BC%80&pwd=666 print(response.json().get('args')) # {'pwd': '666', 'user': 'admin'}
headers
再来看,GET
请求中如何携带headers。
import requests headers = {"user-agent": UserAgent().random} response = requests.get(url='http://www.httpbin.org/get', headers=headers) print(response.json()['headers']['User-Agent']) # Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5
cookies
来看,requests模块如何携带cookis参数。
# 1. 登录,获取cookies值 data = { "userName": "=admin", "password": "1234" } response = requests.post(url="http://www.neeo.cc:6002/pinter/bank/api/login", data=data) print(response.json()) print(response.cookies) print(response.cookies.get_dict()) # 2. 在需要cookies验证的时候,携带上刚才获取到的cookies值 response = requests.get(url='http://www.neeo.cc:6002/pinter/bank/api/query?userName=admin', cookies=response.cookies.get_dict()) print(response.status_code) print(response.json())
文件下载
如果你访问的是一个小文件,或者图片之类的,我们可以直接写入到本地就完了,也就是不用管stream
,让它默认为False即可。
来个美女图片提提神!
import requests import webbrowser url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1568638318957&di=1d7f37e7caece1c39af05b624f42f0a7&imgtype=0&src=http%3A%2F%2Fimg3.duitang.com%2Fuploads%2Fitem%2F201501%2F17%2F20150117224236_vYFmL.jpeg' response = requests.get(url=url) f = open('a.jpeg', 'wb') f.write(response.content) f.close() webbrowser.open('a.jpeg')
老弟,过瘾不?
那要是下载大文件,可就不能这么干了:
import requests import webbrowser url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1568638318957&di=1d7f37e7caece1c39af05b624f42f0a7&imgtype=0&src=http%3A%2F%2Fimg3.duitang.com%2Fuploads%2Fitem%2F201501%2F17%2F20150117224236_vYFmL.jpeg' response = requests.get(url=url, stream=True) with open('a.jpeg', 'wb') as f: for chunk in response.iter_content(chunk_size=256): f.write(chunk) webbrowser.open('a.jpeg')
使用response.iter_content(chunk_size=256)
一块一块下载,并且可以指定chunk_size大小。
当然,也可以使用response.iter_lines
一行一行遍历下载,但是官网说不安全,所以,忘掉它吧。
requests.post()
requests.post(url, data=None, json=None, **kwargs)
发送POST
请求,相关参数:
- url:请求的URL。
- data:可选参数,请求中携带表单编码的字典、bytes或者文件对象。
- json:请求中携带json类型的数据。
- **kwargs:参见requests.request中的kwargs。
在post请求中,data与json既可以是str类型,也可以是dict类型。
区别:
- 不管json是str还是dict,如果不指定headers中的content-type,默认为application/json
- data为dict时,如果不指定content-type,默认为application/x-www-form-urlencoded,相当于普通form表单提交的形式
- data为str时,如果不指定content-type,默认为text/plain
- 用data参数提交数据时,request.body的内容则为
a=1&b=2
的这种形式,用json参数提交数据时,request.body的内容则为'{"a": 1, "b": 2}'
的这种形式
实际应用时候,需要根据后端服务处理的方式来确定
data参数
import requests url = 'http://www.httpbin.org/post' # data为字典 data_dict = {"k1": "v1"} response = requests.post(url=url, data=data_dict) print(response.json()) # data为字符串 data_str = "abc" response = requests.post(url=url, data=data_str) print(response.json(), type(response.json()['data'])) # data为文件对象 file = open('a.jpg', 'rb') response = requests.post(url=url, data=file) print(response.json())
上述的基于data参数上传文件,不如使用专门的files
参数来的合适。
文件上传
基于POST
请求的文件上传,使用files
参数。
import requests file = {"file": open('a.jpg', 'rb')} response = requests.post('http://www.httpbin.org/post', files=file) print(response.json())
json参数
import requests url = 'http://www.httpbin.org/post' response = requests.post(url=url, json={"user": "zhangkai"}) print(response.json())
requests.head()
requests.head(url, **kwargs)
发送HEAD
请求,相关参数:
- url:请求URL。
- **kwargs:参见requests.request中的kwargs。
import requests url = 'http://httpbin.org/get' response = requests.head(url=url) print(response.headers) ''' { 'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Origin': '*', 'Content-Encoding': 'gzip', 'Content-Type': 'application/json', 'Date': 'Mon, 16 Sep 2019 10:58:07 GMT', 'Referrer-Policy': 'no-referrer-when-downgrade', 'Server': 'nginx', 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'DENY', 'X-XSS-Protection': '1; mode=block', 'Connection': 'keep-alive' } '''
使用requests.head(url, **kwargs)
的优点就是以较少的流量获得响应头信息,也可以用在分页中。
requests.put()
requests.put(url, data=None, **kwargs)
发送PUT
请求,相关参数:
- url:请求URL。
- data:可选参数,请求中携带表单编码的字典、bytes或者文件对象。
- **kwargs:参见requests.request中的kwargs。
import requests url = 'http://www.httpbin.org/put' data_dict = {"k1": "v1"} response = requests.put(url=url, data=data_dict) print(response.json()) ''' { 'args': {}, 'data': '', 'files': {}, 'form': {'k1': 'v1'}, 'headers': { 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '5', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'www.httpbin.org', 'User-Agent': 'python-requests/2.19.1' }, 'json': None, 'origin': '1.202.184.14, 1.202.184.14', 'url': 'https://www.httpbin.org/put' } '''
requests.patch()
requests.patch(url, data=None, **kwargs)
发送PATCH
请求,相关参数:
- url:请求URL。
- data:可选参数,请求中携带表单编码的字典、bytes或者文件对象。
- **kwargs:参见requests.request中的kwargs。
import requests url = 'http://www.httpbin.org/patch' data_dict = {"k1": "v1"} response = requests.patch(url=url, data=data_dict) print(response.json()) ''' { 'args': {}, 'data': '', 'files': {}, 'form': {'k1': 'v1'}, 'headers': { 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '5', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'www.httpbin.org', 'User-Agent': 'python-requests/2.19.1' }, 'json': None, 'origin': '1.202.184.14, 1.202.184.14', 'url': 'https://www.httpbin.org/patch' } '''
在requests中,PATCH
请求和PUT
类似。而区别:
PATCH
是对PUT
方法的补充,用来对已知资源进行局部更新。PATCH
相比PUT
更加节省带宽。
requests.delete()
requests.head(url, **kwargs)
发送DELETE
请求,相关参数:
- url:请求URL。
- **kwargs:参见requests.request中的kwargs。
import requests test_url = 'https://api.github.com' def get_url(url): return '/'.join([test_url,url]) email = '24xxxxx48@qq.com' def delete_email(): r = requests.delete(get_url('user/emails'),json = email ,auth=('username','password')) print(r.status_code) print(r.text) print(r.request.headers) delete_email()
将email,用户名,密码,换成自己的GitHub的。
requests.Session()
requests.Session()
可以用来帮我们保持会话。
import requests session = requests.Session() session.get('http://www.httpbin.org/cookies/set/username/root') response = session.get('http://www.httpbin.org/cookies') print(response.json()) # {'cookies': {'username': 'root'}}
证书验证
在之前,这个知识点还能拿12306网站举例的时候.....
如果你请求的https
协议的网址,那么人家网站首先会检测你的证书是否是合法的,如果不合法,会抛出SSLError
。怎么处理呢。
证书验证这里,有两种方式处理。第一种就是使用verify
,是否进行证书校验,默认是True。我们选择不校验。
import requests response = requests.get(url='https://www.12306.cn', verify=False) print(response.status_code)
但有的时候,会有一个Warnning
警告,建议你加证书验证。
我们可以选择忽略这个警告:
import requests from requests.packages import urllib3 urllib3.disable_warnings() response = requests.get(url='https://www.12306.cn', verify=False) print(response.status_code)
也可以选择提供一个CA证书:
import requests response = requests.get(url='https://www.12306.cn', cert=('/path/server.crt', 'path/key')) print(response.status_code)
很明显,我们没有什么CA证书,这就看个热闹吧。
代理设置
代理:就是你访问一个网站,其实并不是你直接访问的,而是你发请求给A机器,A机器取请求B机器。B返回给A,A再返回给你。代理就是中间人的意思。为什么需要代理?因为:反爬虫网站一般使用IP来识别一个机器。老是一个IP在不停访问网站,该网站就会把这个IP拉入黑名单,不允许访问。这时,就需要很多IP再扰乱反爬虫工具的思维,避免封IP。
普通代理
import requests response = requests.get(url='https://www.12306.cn', cert=('/path/server.crt', 'path/key')) print(response.status_code)
代理需要用户名和密码
import requests proxies = { "http": "http://user:password@10.10.1.10:3128", } response = requests.get(url='https://www.12306.cn', proxies=proxies) print(response.status_code)
支持sock代理
想要支持sock代理,那么首先要下载:
pip install requests[socks]
完事在用:
import requests proxies = { 'http': 'socks5://user:pass@host:port', 'https': 'socks5://user:pass@host:port' } respone=requests.get('https://www.12306.cn',proxies=proxies) print(respone.status_code)
超时
超时,在规定的时间无响应。
import requests respone=requests.get('https://www.12306.cn', timeout=0.0001)
认证设置
有些网站,会弹出一个提示框,要求你输入用户名和密码。
import requests from requests.auth import HTTPBasicAuth response = requests.get(url='https://www.12306.cn', auth=HTTPBasicAuth(username='user', password='123')) print(response.status_code) HTTPBasicAuth的简写形式: import requests response = requests.get(url='https://www.12306.cn', auth=('user', '123')) print(response.status_code)
异常处理
异常处理相关异常类主要在requests.exceptions
下,可以根据需求去翻看源码。
import requests from requests.exceptions import ReadTimeout, ConnectionError, RequestException try: # RequestException # response = requests.get(url='https://www.12306.com') # ReadTimeout # response = requests.get(url='https://www.12306.cn', timeout=0.01) # ConnectionError ,断网演示... response = requests.get(url='https://xueqiu.com/stock/f10/finmainindex.json') # print(response.status_code) except ReadTimeout as e: print('ReadTimeout:', e) except ConnectionError as e: print('ConnectionError:', e) except RequestException as e: print('RequestException:', e)