简介
Requests是用python语言基于urllib编写的,采用的是Apache2 Licensed开源协议的HTTP库,Requests它会比urllib更加方便,可以节约我们大量的工作。
安装
pip快速安装
pip3 install requests
使用
先上一串代码
response.text返回的是Unicode格式,通常需要转换为utf-8格式,否则就是乱码。response.content是二进制模式,可以下载视频之类的,如果想看的话需要decode成utf-8格式。
不管是通过response.content.decode("utf-8)的方式还是通过response.encoding="utf-8"的方式都可以避免乱码的问题发生
import requests
response = requests.get("https://www.baidu.com")
print(type(response))
print(response.status_code)
print(type(response.text))
response.encoding = "utf-8"
print(response.text)
print(response.cookies)
print(response.content)
print(response.content.decode("utf-8"))
请求方式
HTTP请求的方法:
HTTP/1.1协议中共定义了八种方法(有时也叫“动作”),来表明Request-URL指定的资源不同的操作方式。
HTTP1.0定义了三种请求方法:GET, POST 和 HEAD方法。
HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法
- 1.OPTIONS
返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性。 - 2.HEAD
向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。 - 3.GET
向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在Web Application中,其中一个原因是GET可能会被网络蜘蛛等随意访问。Loadrunner中对应get请求函数:web_link和web_url
- 4.POST
向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 Loadrunner中对应POST请求函数:web_submit_data,web_submit_form
- 5.PUT
向指定资源位置上传其最新内容。 - 6.DELETE
请求服务器删除Request-URL所标识的资源。 - 7.TRACE
回显服务器收到的请求,主要用于测试或诊断。 - 8.CONNECT
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
注意:
1)方法名称是区分大小写的,当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Mothod Not Allowed);当服务器不认识或者不支持对应的请求方法时,应返回状态码501(Not Implemented)。
2)HTTP服务器至少应该实现GET和HEAD/POST方法,其他方法都是可选的,此外除上述方法,特定的HTTP服务器支持扩展自定义的方法。
import requests
r1 = requests.post("http://httpbin.org/post")
r2 = requests.put("http://httpbin.org/put")
r3 = requests.delete("http://httpbin.org/delete")
r4 = requests.head("http://httpbin.org/get")
r5 = requests.options("http://httpbin.org/get")
print(r1)
print(r2)
print(r3)
print(r4)
print(r5)
基本Get
import requests
url = 'https://www.baidu.com'
response = requests.get(url)
print(response.text)
带参数的GET请求
如果想查询http://httpbin.org/get
页面的具体参数,需要在url里面加上,例如我想看有没有Host=httpbin.org这条数据,url形式应该是http://httpbin.org/get?Host=httpbin.org
下面提交的数据是往这个地址传送data里面的数据。
import requests
url = 'http://httpbin.org/get'
data = {
'name':'zhangsan',
'age':'25'
}
response = requests.get(url,params=data)
print(response.url)
print(response.text)
json数据
从下面的数据中我们可以得出,如果结果:
requests中response.json()
方法等同于json.loads(response.text)
方法。
import requests
import json
response = requests.get("http://httpbin.org/get")
print(type(response.text))
print(response.text)
print(response.json())
print(json.loads(response.text))
print(type(response.json()))
添加header
import requests
url = 'https://www.zhihu.com/'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'
}
response = requests.get(url,headers=headers)
print(response.text)
基本post请求
通过post把数据提交到url地址,等同于以字典的形式提交form表单里面的数据。
import requests
url = 'https://httpbin.org/post'
data = {
'name':'jack',
'age':'23'
}
response = requests.post(url,data=data)
print(response.text)
执行结果:
{
"args": {},
"data": "",
"files": {},
"form": {
"age": "23",
"name": "jack"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "16",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.24.0",
"X-Amzn-Trace-Id": "Root=1-61386488-14f223f6476ba61903060b45"
},
"json": null,
"origin": "101.230.216.177",
"url": "https://httpbin.org/post"
}
响应
import requests
response = requests.get("http://www.baidu.com")
# 打印请求页面的状态码
print(type(response.status_code),response.status_code)
# 打印请求网址的headers所有信息
print(type(response.headers),response.headers)
# 打印请求网址的cookies信息
print(type(response.cookies),response.cookies)
# 打印请求网址的地址
print(type(response.url),response.url)
# 打印请求的历史记录(以列表的形式显示)
print(type(response.history),response.history)
执行结果:
<class 'int'> 200
<class 'requests.structures.CaseInsensitiveDict'> {'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform',
'Connection': 'keep-alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Date': 'Wed, 08 Sep 2021 07:27:36 GMT', 'Last-Modified': 'Mon, 23 Jan 2017 13:27:36 GMT', 'Pragma': 'no-cache', 'Server': 'bfe/1.0.8.18', 'Set-Cookie': 'BDORZ=27315; max-age=86400; domain=.baidu.com; path=/', 'Transfer-Encoding': 'chunked'}
<class 'requests.cookies.RequestsCookieJar'> <RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
<class 'str'> http://www.baidu.com/
<class 'list'> []
内置状态码
100: ('continue',),
101: ('switching_protocols',),
102: ('processing',),
103: ('checkpoint',),
122: ('uri_too_long', 'request_uri_too_long'),
200: ('ok', 'okay', 'all_ok', 'all_okay', 'all_good', '\\o/', '✓'),
201: ('created',),
202: ('accepted',),
203: ('non_authoritative_info', 'non_authoritative_information'),
204: ('no_content',),
205: ('reset_content', 'reset'),
206: ('partial_content', 'partial'),
207: ('multi_status', 'multiple_status', 'multi_stati', 'multiple_stati'),
208: ('already_reported',),
226: ('im_used',),
# Redirection.重定向
300: ('multiple_choices',),
301: ('moved_permanently', 'moved', '\\o-'),
302: ('found',),
303: ('see_other', 'other'),
304: ('not_modified',),
305: ('use_proxy',),
306: ('switch_proxy',),
307: ('temporary_redirect', 'temporary_moved', 'temporary'),
308: ('permanent_redirect',
'resume_incomplete', 'resume',), # These 2 to be removed in 3.0
# Client Error.客户端错误
400: ('bad_request', 'bad'),
401: ('unauthorized',),
402: ('payment_required', 'payment'),
403: ('forbidden',),
404: ('not_found', '-o-'),
405: ('method_not_allowed', 'not_allowed'),
406: ('not_acceptable',),
407: ('proxy_authentication_required', 'proxy_auth', 'proxy_authentication'),
408: ('request_timeout', 'timeout'),
409: ('conflict',),
410: ('gone',),
411: ('length_required',),
412: ('precondition_failed', 'precondition'),
413: ('request_entity_too_large',),
414: ('request_uri_too_large',),
415: ('unsupported_media_type', 'unsupported_media', 'media_type'),
416: ('requested_range_not_satisfiable', 'requested_range', 'range_not_satisfiable'),
417: ('expectation_failed',),
418: ('im_a_teapot', 'teapot', 'i_am_a_teapot'),
421: ('misdirected_request',),
422: ('unprocessable_entity', 'unprocessable'),
423: ('locked',),
424: ('failed_dependency', 'dependency'),
425: ('unordered_collection', 'unordered'),
426: ('upgrade_required', 'upgrade'),
428: ('precondition_required', 'precondition'),
429: ('too_many_requests', 'too_many'),
431: ('header_fields_too_large', 'fields_too_large'),
444: ('no_response', 'none'),
449: ('retry_with', 'retry'),
450: ('blocked_by_windows_parental_controls', 'parental_controls'),
451: ('unavailable_for_legal_reasons', 'legal_reasons'),
499: ('client_closed_request',),
# Server Error.服务端错误
500: ('internal_server_error', 'server_error', '/o\\', '✗'),
501: ('not_implemented',),
502: ('bad_gateway',),
503: ('service_unavailable', 'unavailable'),
504: ('gateway_timeout',),
505: ('http_version_not_supported', 'http_version'),
506: ('variant_also_negotiates',),
507: ('insufficient_storage',),
509: ('bandwidth_limit_exceeded', 'bandwidth'),
510: ('not_extended',),
511: ('network_authentication_required', 'network_auth', 'network_authentication'),
import requests
response = requests.get('http://www.jianshu.com/404.html')
# 使用requests内置的字母判断状态码
# 如果response返回的状态码是非正常的就返回404错误
if response.status_code != requests.codes.ok:
print('404')
# 如果页面返回的状态码是200,就打印下面的状态
response = requests.get('https://www.baidu.com')
if response.status_code == 200:
print('200')
执行结果:
404
200
requests的高级操作
文件上传
import requests
url = "http://httpbin.org/post"
files = {"files":open("test.jpg","rb")}
response = requests.post(url,files=files)
print(response.text)
获取cookie
import requests
response = requests.get('https://www.baidu.com')
print(response.cookies)
for key,value in response.cookies.items():
print(key,'==',value)
执行结果:
<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
BDORZ == 27315
cookie与session的区别
简易版:
- 1.session在服务器端,cookie 在客户端(浏览器)
- 2.session默认被存在在服务器的一个文件里(不是内存)
- 3.session的运行依赖session id,而session id是存在cookie中的,也就是说,如果浏览器禁用了cookie,同时,session也会失效(但是可以通过其它方式实现,比如在url中传递session_id)
- 4.session可以放在文件、数据库、或内存中都可以。
- 5.用户验证这种场合一般会用session。因此,维持一个会话的核心就是客户端的唯一标识,即session id。
详细版:
- 1.由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放 Session。
- 2.思考一下服务端如何识别特定的客户?这个时候Cookie就登场了。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。有人问,如果客户端的浏览器禁用了 Cookie 怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。
- 3.Cookie其实还可以用在一些方便用户的场景下,设想你某次登陆过一个网站,下次登录的时候不想再次输入账号了,怎么办?这个信息可以写到Cookie里面,访问网站的时候,网站页面的脚本可以读取这个信息,就自动帮你把用户名给填了,能够方便一下用户。这也是Cookie名称的由来,给用户的一点甜头。
- 4.总结一下:Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;
Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
http是无状态协议
无状态是指,当浏览器给服务器发送请求的时候,服务器响应客户端请求。但是当同一个浏览器再次发送请求给服务器的时候,服务器并不知道他就是刚才的那个浏览器。简单的说,就是服务器不会去记得你,所以就是http的无状态协议。
会话维持
cookie的一个作用就是可以用于模拟登陆,做会话维持。
import requests
session = requests.session()
session.get('http://httpbin.org/cookies/set/number/123456')
response = session.get('http://httpbin.org/cookies')
print(response.text)
执行结果:
{
"cookies": {
"number": "123456"
}
}
证书验证
无证书访问
import requests
response = requests.get('https://www.12306.cn')
# 在请求https时,requests会进行证书的验证,如果验证失败则会抛出异常
print(response.status_code)
关闭证书验证
import requests
# 关闭验证,但是仍然会报出证书警告
response = requests.get('https://www.12306.cn',verify=False)
print(response.status_code)
消除验证证书的警报
import requests
from requests.packages import urllib3
urllib3.disable_warnings()
response = requests.get('https://www.12306.cn',verify=False)
print(response.status_code)
手动设置证书
import requests
# 证书路径,写真实的
response = requests.get('https://www.12306.cn',cert=('/path/server.crt','/path/key'))
print(response.status_code)
代理设置
设置普通代理
import requests
proxies = {
"http":"http://127.0.0.1:9743",
"https":"https://127.0.0.1:9743",
}
response = requests.get("https://www.taobao.com",proxies=proxies)
print(response.status_code)
设置用户名和密码代理
import requests
proxies = {
"http": "http://user:password@127.0.0.1:9743",
}
response = requests.get("https://www.taobao.com",proxies=proxies)
print(response.status_code)
超时时间
通过timeout参数可以设置超时的时间
import requests
from requests.exceptions import ReadTimeout
try:
# 设置必须在500ms内收到响应,不然或抛出ReadTimeout异常
response = requests.get("http://httpbin.org/get",timeout=0.5)
print(response.status_code)
except ReadTimeout:
print('timeout')
认证设置
通过碰到需要认证的网站可以通过requests.auth模块实现
import requests
from requests.auth import HTTPBasicAuth
# 方法一:
# r = requests.get('http://120.27.34.24:9001', auth=HTTPBasicAuth('user','123'))
# 方法二:
r = requests.get('http://120.27.34.24:9001',auth=('user','123'))
print(r.status_code)
异常处理
关于reqeusts的异常在这里可以看到详细内容:http://www.python-requests.org/en/master/api/#exceptions
所有的异常都是在requests.excepitons中。
从源码我们可以看出
RequestException继承IOError,
HTTPError,ConnectionError,Timeout继承RequestionException
ProxyError,SSLError继承ConnectionError
ReadTimeout继承Timeout异常
这里列举了一些常用的异常继承关系,详细的可以看:http://cn.python-requests.org/zh_CN/latest/_modules/requests/exceptions.html#RequestException
通过下面的例子进行简单的演示:
import requests
from requests.exceptions import ReadTimeout,ConnectionError,RequestException
try:
response = requests.get("http://httpbin.org/get",timeout=0.5)
print(response.status_code)
except ReadTimeout:
print('Timeout')
except ConnectionError:
print('Connection error')
except RequestException:
print('Error')
首先被捕捉的异常是timeout,当把网络断掉的haul就会捕捉到ConnectionError,如果前面异常都没有捕捉到,最后也可以通过RequestExctption捕捉到。