主要介绍以下内容
1.发送HTTP请求
2.设置HTTP请求头
3.抓取二进制数据
4.POST请求
5.响应数据
6.上传文件
7.处理Cookie
8.维持会话
9.SSL证书验证
10.使用代理
11.超时处理
12.身份验证
13.打包请求
一.发送HTTP请求
urllib库中的urlopen方法实际上是以GET方法请求网页,而requests中对应的方法是get,该方法可以接收一个url,然后会返回一个对象,通过get方法的返回值,可以获取HTTP响应数据
1.1使用get方法访问淘宝首页,并获取get方法返回值类型、状态码、响应体、Cookie等信息(出错 SSLError)
import requests
# 屏蔽warning信息
# requests.packages.urllib3.disable_warnings() # 屏蔽也不行,不是urllib3的把,要requests
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36 '}
r = requests.get('https://www.taobao.com',headers=headers) # raise SSLError(e, request=request);
print(type(r))
print(r.status_code)
print(type(r.text))
print(r.cookies)
print(r.text)
get方法返回的是一个requests.model.Response类型的对象
1.2GET请求
要想未get请求指定参数,可以直接将参数加在URL后面,用问号(?)分隔,不过还有另外一种更好的方法,就是使用get方法的params参数,该参数是一个字典类型的值,在字典中每一对key-value,就是一对参数值。如果同时在URL和params参数指定GET请求的参数,那么get方法会将参数合并。如果出现同名的参数,会用列表存储,也就是同名参数的值会按出现的先后顺序保存在列表中
本例使用get方法访问http://httpbin.org/get,并同时使用url和params参数的方式设置GET请求参数,并返回输出结果
import requests
data = {
'name':'Bill',
'country':'中国',
'age':20
}
r = requests.get('http://httpbin.org/get?name=Mike&country=美国&age=40',params=data)
print(r.text)
print(r.json())
print(r.json()['args']['country'])
二.设置HTTP请求头
2.1添加HTTP请求头
使用get方法访问http://httpbin.org/get,并设置了一些请求头,包括User-Agent和一个自定义请求头name,其中name的值为中文
import requests
from urllib.parse import quote,unquote
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36',
'name':quote('李宁')
}
r = requests.get('http://httpbin.org/get',headers=headers)
print(r.text)
print('Name:',unquote(r.json()['headers']['Name']))
三.抓取二进制数据
本例使用get方法抓取一个png格式的图像文件,并将其保存为本地文件
import requests
r = requests.get('http://t.cn/EfgN7gz')
print(r.text)
with open('Python从菜鸟到高手.png','wb') as f:
f.write(r.content)
四。POST请求
在发送POST请求时需要指定data参数,该参数是一个字典类型的值,每一对key-value是一对POST请求参数(表单字段)
import requests
data = {
'name':'Bill',
'country':'中国',
'age':20
}
r = requests.post('http://httpbin.org/post',data=data)
print(r.text)
print(r.json())
print(r.json()['form']['country'])
五。响应数据
使用get方法向简书发送一个请求,然后得到并输出相应的响应结果
import requests
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36',
}
r = requests.get('http://www.jianshu.com',headers=headers)
print(type(r.status_code),r.status_code)
print(type(r.headers),r.headers)
print(type(r.cookies),r.cookies)
print(type(r.url),r.url)
print(type(r.history),r.history)
if not r.status_code == requests.codes.okay:
print("failed")
else:
print("ok")
requests提供了一个code对象,可以直接查看状态码对应的标识(一个字符串),在<requests根目录目录>/requests/status_codes.py
_codes = {
# Informational.
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'),
}
六.上传文件
在运行本例之前,应先运行upload_server.py文件
采用的是Post方法的files参数,files参数的值可以是BufferedReader对象,该对象可以用Python语言的内置函数open返回;就是一个字典形式,file为键的字典,值为打开一个文件的对象。
import requests
files1 = {'file':open('Python从菜鸟到高手.png','rb')}
r1 = requests.post('http://127.0.0.1:5000', files=files1)
print(r1.text)
files2 = {'file':open('Python从菜鸟到高手.png','rb')}
r2 = requests.post('http://httpbin.org/post',files=files2)
print(r2.text)
7.处理Cookie(cookie失效,我也不知道如何用cookie返回原有保持cookie的值)
有两种方式设置Coolie:1.headers参数;2.cookies参数
7.1Get和Post方法都有这两个参数,如果使用cookies参数,需要创建RequestsCookieJar对象,并使用set方法设置每一个Cookie
import requests
r1 = requests.get('http://www.baidu.com')
print(r1.cookies)
for key,value in r1.cookies.items():
print(key,'=',value)
# 获取简书首页内容
headers = {
'Host':'www.jianshu.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36',
'Cookie': 'sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2226065565%22%2C%22first_id%22%3A%2217b59029450769-04d60dc1f07d6d-c343365-921600-17b59029451bcc%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_utm_source%22%3A%22desktop%22%2C%22%24latest_utm_medium%22%3A%22timeline%22%7D%2C%22%24device_id%22%3A%2217b59029450769-04d60dc1f07d6d-c343365-921600-17b59029451bcc%22%7D'
}
r2 = requests.get('https://www.jianshu.com',headers=headers)
print(r2.text)
另外一种设置Cookie的方式
requests.cookies.RequestsCookieJar()
jar.set(key,value)
headers = {
'Host':'www.jianshu.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36',
}
cookies = 'sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2226065565%22%2C%22first_id%22%3A%2217b59029450769-04d60dc1f07d6d-c343365-921600-17b59029451bcc%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_utm_source%22%3A%22desktop%22%2C%22%24latest_utm_medium%22%3A%22timeline%22%7D%2C%22%24device_id%22%3A%2217b59029450769-04d60dc1f07d6d-c343365-921600-17b59029451bcc%22%7D'
jar = requests.cookies.RequestsCookieJar()
for cookie in cookies.split(';'):
key, value = cookie.split('=',1)
jar.set(key,value)
r3 = requests.get('http://www.jianshu.com',cookies = jar,headers=headers)
print(r3.text)
八.维持会话(使用同一会话)
在requests中为我们提供了Session对象,可以在无需用户干预Cookie的情况下维持Session.达到不断向服务端发送同一个ID,客户端就可以在服务端找到对应的Session对象,一些爬虫需要作为同一个客户端来多次抓取页面,也就是说这些抓取动作需要在同一个Session中完成。通过Session对象的get、post等方法可以在同一个Session中向服务端发送请求。
这里分别使用传统的方法和Session对象向服务端发送请求,并通过url设置Cookie
可以使用requests.Session()赋值给一个对象,然后改对象再用get请求方式请求url,这样下次请求时就有改cookie字段在返回的响应体中
import requests
# 不使用Session
requests.get('http://httpbin.org/cookies/set/name/Bill')
r1 = requests.get('http://httpbin.org/cookies')
print(r1.text)
# 使用Session
session = requests.Session()
session.get('http://httpbin.org/cookies/set/name/Bill')
r2 = session.get('http://httpbin.org/cookies')
print(r2.text)
不使用Session对象,第二次请求无法获得第一次请求的Cookie.反之,可以
九.SSL证书验证
nginx搭建HTTPPS服务器,然后通过requests发送请求,并捕捉证书验证(待补;nginx在windows下怎么用,如歌生成自己的签名证书 ssl)
十.使用代理(该代理失效)
指定proxies参数,该参数是一个字典类型的值,每一对key-value表示一个代理的协议,如http,https
本例设置了HTTP和HTTPS代理,并通过代理访问天猫首页,最后输出响应内容
import requests
proxies = {
'http':'http://144.123.68.152:25653',
'https':'http://144.123.68.152:25653'
}
r = requests.get('https://www.tmall.com/',proxies=proxies)
print(r.text)
十一.超时
import requests,requests.exceptions
try:
r = requests.get('https://www.jd.com',timeout = 0.001)
print(r.text)
except requests.exceptions.Timeout as e:
print(e)
# 抛出连接超时异常
requests.get('https://www.jd.com', timeout=(0.01, 0.001))
# 永久等待,不会抛出超时异常
requests.get('https://www.jd.com', timeout=None)
十二.身份验证
requests包进行身份验证只需设置auth即可,auth参数的值是一个HTTPBasicAuth对象,封装了用户名和密码;运行之前编写的AuthServer.py文件,这是一个支持Basic验证的服务器
import requests
from requests.auth import HTTPBasicAuth
r = requests.get('http://localhost:5000',auth=HTTPBasicAuth('bill','1234'))
print(r.status_code)
print(r.text)
十三.将请求打包
在使用urllib时,可以将请求打包,也就是将所有要发送给服务端的请求信息都放到Request对象中,然后直接发送这个对象即可。requests也可以完成同样工作,在requests中也有一个Request类,用于封装请求信息,然后调用Session的prepare_request方法处理Request对象,并返回一个requests.model.Response对象,最后通过Session.send方法发送Response对象
本例使用Request对象封装请求,通过Session.send方法发送请求,然后输出响应结果
from requests import Request,Session
url = 'http://httpbin.org/post'
data = {
'name':'Bill',
'age':30
}
headers = {
'country':'China'
}
session = Session()
req = Request('post',url,data=data,headers=headers)
prepared = session.prepare_request(req)
r = session.send(prepared)
print(type(r))
print(r.text)