安装request库。
pip install request
request库中以GET方式请求网页的方法就是get()方法
import requests
r = requests.get('https://www.baidu.com/')
print(type(r))
print(r.status_code)
print(type(r.text))
print(r.text)
print(r.cookies)
'''
运行结果:
200
ç™¾åº¦ä¸€ä¸‹ï¼Œä½ å°±çŸ¥é“
]>
'''
这里调用的get()方法和urllib的urlopen()方法操作相同。得到了一个Response对象,然后分别输出Response的类型、状态码、响应体类型、内容、cookies。
通过运行结果发现,它返回类型是:requests.models.Response
响应体的类型是字符串str,cookies的类型是:RequestsCookieJar。
其他类型的请求依然可以用一句话来完成。
r = requests.post('http://httpbin.org/post')
r = requests.put('http://httpbin.org/post')
r = requests.delete('http://httpbin.org/post')
r = requests.head('http://httpbin.org/post')
r = requests.options('http://httpbin.org/post')
基本实例
首先构造一个最简单的GET请求,请求的连接为http://httpbin.org/get 该网站会判断如果客户端发起的是GET请求的话,它返回相应的请求信息。
import requests
r = requests.get('http://httpbin.org/get')
print(r.text)
'''
运行结果:
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0",
"X-Amzn-Trace-Id": "Root=1-601a6499-085939cc227cef8e10512ec9"
},
"origin": "101.27.236.254",
"url": "http://httpbin.org/get"
}
'''
返回结果中包含请求头、URL、IP等信息。
那么,对于GET请求,如果要附加额外的信息。一般怎么添加呢?
可以直接写成:
requests.get('http://httpbin.org/get?name=germey&age=22')
还可以这么写:
import requests
data = {
'name': 'germey',
'age': 22
}
r = requests.get('http://httpbin.org/get', params=data)
print(r.text)
'''
运行结果:
{
"args": {
"age": "22",
"name": "germey"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0",
"X-Amzn-Trace-Id": "Root=1-601a660f-267a57e67038f33a6a9f8471"
},
"origin": "101.27.236.254",
"url": "http://httpbin.org/get?name=germey&age=22"
}
'''
通过运行结果可以判断,请求链接自动被构造成了:http://httpbin.org/get?name=germey&age=22
另外网页返回的数据实际上是个str类型的数据,但是格式是JSON格式的。如果想直接解析返回结果,需要得到一个字典格式的话,可以使用json()方法:
import requests
r = requests.get('http://httpbin.org/get')
print(type(r.text))
print(r.json())
print(type(r.json()))
'''
运行结果:
{'args': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.22.0', 'X-Amzn-Trace-Id': 'Root=1-601a6708-6670d3d14537c91e05517042'}, 'origin': '101.27.236.254', 'url': 'http://httpbin.org/get'}
'''
调用json方法,就可以将返回的结果是JSON格式的字符串转换为字典。
如果返回的结果不是JSON格式的,使用json()方法将会解析错误。抛出json.decoder.JSONDecodeError异常。
抓取网页
import requests
import re
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'
}
r = requests.get('https://www.zhihu.com/explore', headers=headers)
pattern = re.compile('explore-feed.*?question_link.*?>(.*?)', re.S)
titles = re.findall(pattern, r.text)
print(titles)
这里加入了headers,其中包含了User-Agent。也就是浏览器标识信息。如果没有知乎进制爬取。
使用了正则表达式来匹配了所有问题内容。
抓取二进制数据
如果想要抓取图片、音频、视频等文件,应该怎么办?它们这些文件本质上都是由二进制组成的,想要抓取它们,就要拿到他们的二进制码。
以爬取GitHub的站点图标为例:
import requests
r = requests.get('https://github.com/favicon.ico')
print(r.text)
print(r.content)
'''
r.content 返回的是response的二进制形式
'''
将刚提取的照片,保存下来:
import requests
r = requests.get('https://github.com/favicon.ico')
with open('favicon.ico', 'wb') as f:
f.write(r.content)
这里利用了open()方法,它的第一个参数是文件名称,第二个参数代表以二进制形式打开,可以想文件写入二进制数据。
运行结果,可以发现在文件夹中出现了名为favicon.icn的图标。
同样,音频和视频也可以用同样的方式获取。
添加headers
我们可以通过添加headers参数来传递请求头信息。
比如,上面的知乎例子中,如果不传递请求头,就不能正常请求:
import requests
r = requests.get('https://www.zhihu.com/explore')
print(r.status_code)
# 结果:403
如果添加了请求头:
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'
}
r = requests.get('https://www.zhihu.com/explore', headers=headers)
print(r.status_code)
# 结果:200
使用requests发送POST请求,同样非常简单:
import requests
data = {
'name': 'gremey',
'age': 22
}
r = requests.post('http://httpbin.org/post', data=data)
print(r.text)
这里请求的是http://httpbin.org/post,该网站可以判断如果请求是POST方式,就把相关信息返回。
{
"args": {},
"data": "",
"files": {},
"form": {
"age": "22",
"name": "gremey"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "18",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0",
"X-Amzn-Trace-Id": "Root=1-601aa10d-42d913880494d70138da87b0"
},
"json": null,
"origin": "101.**.***.***",
"url": "http://httpbin.org/post"
}
text:响应的内容 ,
content:响应的内容(二进制格式),
status_code:状态码,
headers:响应头,
cookies:Cookies,
url:得到URL,
history:请求历史,
requests还提供了一个内置的状态码查询对象 requests.codes:
import requests
r = requests.get('http://www.jianshu.com')
if r.status_code == requests.codes.ok:
print(r.status_code)
else:
print(r.status_code)
import requests
files = {'file': open('favicon.ico', 'rb')}
r = requests.post('http://httpbin.org/post', files=files)
print(r.text)
'''
{
"args": {},
"data": "",
"files": {
"file": "data:application/octet-stream;base64,AAA......AA="
},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "6666",
"Content-Type": "multipart/form-data; boundary=a31bbf46d658d1fc60329fbddb902743",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0",
"X-Amzn-Trace-Id": "Root=1-601b9a26-56bdf162129937eb1bfbb260"
},
"json": null,
"origin": "101.27.236.254",
"url": "http://httpbin.org/post"
}
'''
先创建一个字典,字典里的值就是文件。然后在使用POST请求的时候,给参数复制于刚刚建立的文件字典。
通过结果观察可知道,上传文件会单独创建一个files字段。该字段内容就是文件字典内的内容。而form字段为空,这证明文件上传部分会单独有一个files字段来标识。
import requests
r = requests.get('https://www.baidu.com')
print(r.cookies)
for key,value in r.cookies.items():
print(key, '=', value)
'''
]>
BDORZ = 27315
'''
首先调用cookies属性即可获得Cookies,可以发现它是RequestsCookieJar类型的。然后调用items()方法将其转换为元组组成的列表,遍历每一个Cookie的名称和值,实现Cookie的遍历和解析。
当然,也可以用cookies来维持登录状态,以知乎为例:
import requests
headers = {
'User-Agent': 'Mozi......',
'Cookie':'_zap=3f......'
}
r = requests.get('https://www.zhihu.com', headers=headers)
print(r.text)
也可以通过cookies参数来设置,这样就需要先构建一个RequestsCookieJar对象。
import requests
cookies = '_zap=3f00e0......'
jar = requests.cookies.RequestsCookieJar()
headers = {
'Host': 'www.zhihu.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.1'
'46 Safari/537.36'
}
for cookie in cookies.split(';'): # 使用分号进行分割
key, value = cookie.split('=', 1) # 使用等号进行分割,分割1次
jar.set(key, value)
r = requests.get('http://www.zhihu.com', cookies=jar, headers=headers)
print(r.text)
设置一个cookies变量,保存一个cookie。
设置一个headers,保存User-Agent,Host等一些请求头。
实例化一个RequestsCookieJar对象。
使用for循环将cookies变量里的cookie使用split()方法按照分号(;)进行切割。然后在对切割后的cookie使用split()方法用等号切割,第二个参数1,表示切割一次。等号前的内容保存到key中,等好后的内容保存到value中。然后在使用set()方法,将key和value添加到实例化的RequestsCookieJar对象中。
在requests中,如果直接使用get()或post()请求虽然可以做到模拟网页请求,但是实际上相当于不同的会话,也就是说相当于打开了两个浏览器打开了不同的页面。
假设:第一个请求利用post()方法登陆了某个网站,第二次想获取网站成功登陆后的自己的个人信息,你又用get()方法去请求个人信息页面。实际上,这相当于打来了两个浏览器。是两个完全不相关的会话,不能获取到个人信息。
解决办法:维持同一个会话,也就是相当于打开一个新浏览器选项卡而不是在新开一个浏览器。但是又不想重复设置cookies,就需要利用Session对象了。
import requests
requests.get('http://httpbin.org/cookies/set/number/123456789')
r = requests.get('http://httpbin.org/cookies')
print(r.text)
'''
requests.get('http://httpbin.org/cookies/set/number/123456789')
上面请求的网址可以设置一个cookie,名为number,内容是123456789
结果:
{
"cookies": {}
}
'''
通过结果看到,cookies字段为空,并没有刚刚设置的cookie。
下面使用Session对象试试:
import requests
s = requests.session()
s.get('http://httpbin.org/cookies/set/number/123456789')
r = s.get('http://httpbin.org/cookies')
print(r.text)
'''
结果:
{
"cookies": {
"number": "123456789"
}
}
'''
通过上面的结果,发现cookies字段有内容了,键是number,值是123456789。
实现步骤:
先使用requests.session()生成一个Session对象。
然后使用Session对象请求http://httpbin.org/cookies/set/number/123456789,生成一个cookie。
再使用Session对象调用get()方法去访问http://httpbin.org/cookies。
get()方法或者post()方法中,设置verify参数,True:自动验证,False:不验证
需要用到:proxies参数:
import requests
proxies = {
'http': 'http://10.10.1.10:3128',
'https': 'https://10.10.1.10:1080'
}
requests.get('https://www.toabo.com', proxies=proxies)
若需要使用HTTP Basic Auth代理,可以使用类似http://ueser:password@host:port这样的语法来设置
import requests
proxies = {
'http': 'http://user:[email protected]:3128'
}
requests.get('https://www.toabo.com', proxies=proxies)
除了基本代理,还可以使用SOCKS协议代理
首先需要安装socks这个库
pip install requests[socks]
然后就可以使用SOCKS协议代理了
import requests
proxies = {
'http': 'socks5://user:password@host:port',
'https': 'socks5://user:password@host:port'
}
requests.get('https://www.toabo.com', proxies=proxies)
需要用到timeout参数
import requests
requests.get('http://www.taobao.com', timeout=1)
提示timeout分为两个阶段,连接和读取
上面设置的timeout是用作连接和读取这二者的timeout的总和。
如果要分别制定,就可以传入一个元组:
import requests
requests.get('http://www.taobao.com', timeout=(5, 11))
还可以那个timeout设置为None,或者不设置直接留空,因为默认是None。这样就是不设置超时:
import requests
requests.get('http://www.taobao.com', timeout=None)
可以用rquests.auth里面的HTTPBasicAuth
import requests
from requests.auth import HTTPBasicAuth
r = requests.get('htpps://......', auth=HTTPBasicAuth('username', 'password'))
print(r.status_code)
# 简写
import requests
from requests.auth import HTTPBasicAuth
r = requests.get('htpps://......', auth=('username', 'password'))
print(r.status_code)
还提供了其他认证,比如OAuth认证。
pip install requests_oauthlib
import requests
from requests_oauthlib import OAuth1
url = 'https://api.twiter.com/1.1/account/verify_credertials.json'
auth = OAuth1('YOUR_APP_KEY', 'YOUR_APP_SECRET', 'USER_OAUTH_TOKEN', 'USER_OAUTH_TOKEN_SECRET')
requests.get(url, auth=auth)
将请求表示为数据结构。
from requests import Request, Session
url = 'http://httpbin.org/post'
data = {
'name': 'dong'
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.14'
'6 Safari/537.36'
}
s = Session()
req = Request(method='post', url=url, data=data, headers=headers)
prepped = s.prepare_request(req)
r = s.send(prepped)
print(r.text)
'''
结果:
{
"args": {},
"data": "",
"files": {},
"form": {
"name": "dong"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "9",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.146 Safari/537.36",
"X-Amzn-Trace-Id": "Root=1-601e8c1b-6b0b817b39c1cf05141f0c75"
},
"json": null,
"origin": "101.27.236.254",
"url": "http://httpbin.org/post"
} `
'''