爬虫day02:爬虫请求库之requests库
本帖最后由 淘小欣 于 2021-5-29 22:16 编辑# 02.爬虫请求库之requests库
## 一、requests模块介绍
### 1.介绍:
+ 使用requests可以模拟浏览器发送HTTP的请求
+ 不仅仅用来做爬虫,服务之间的调用也使用它
+ HTTP情趣请求头,请求体,请求地址都可以使用这个模块
+ requests是基于python urllib2模块封装的,这个模块用起来比较繁琐
>注意:requests库发送请求将网页内容下载下来以后,并不会执行js代码,这需要我们自己分析目标站点然后发起新的request请求
### 2.安装
```bash
pip3 install requests
```
### 3.各种请求方式
+ 各种请求方式:常用的就是`requests.get()`和`requests.post()`
```python
>>> import requests
>>> r = requests.get('https://api.github.com/events')
>>> r = requests.post('http://httpbin.org/post', data = {'key':'value'})
>>> r = requests.put('http://httpbin.org/put', data = {'key':'value'})
>>> r = requests.delete('http://httpbin.org/delete')
>>> r = requests.head('http://httpbin.org/get')
>>> r = requests.options('http://httpbin.org/get')
```
## 二、requests模块发送get请求
### 1.基本get请求
```python
import requests
# response是响应对象,http响应封装了,响应体
response = requests.get('https://weread.qq.com/')
# 把响应体的数据转成了字符串
print(response.text)
# 示例 向百度发送请求
res=requests.get('https://www.baidu.com/')
# print(res.text)
# 将爬取的数据写入到文件中
with open('baidu.html','wb') as f:
f.write(res.content) # 响应体二进制内容
```
### 2.带参数的GET请求->params
+ 将数据拼在路径中
+ 在请求头中携带`user-agent`(客户端类型),(https://baike.baidu.com/item/HTTP_REFERER/5358396?fr=aladdin)
#### 2.1请求地址中携带数据方式一: 直接携带 (中文一般不会进行url编码, 会出现编码问题)
```python
import requests
header = {
# 模拟浏览器
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'
# 可以解决防盗链问题,没有可以不写
'referer': ''
}
res = requests.get('https://www.baidu.com/s?wd=%E7%BE%8E%E5%A5%B3', headers=header)
print(res.text)
```
>**注意**:
>
>如果你发送请求去一个地址,拿不到数据或者拿到的数据不对的原因是什么?你模拟的不像浏览器,把请求头的数据和该带的带上
#### 2.2 使用params来传递get请求参数(中文自动进行url编码)
```python
import requests
header = {
# 模拟浏览器
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'
}
res = requests.get('https://www.baidu.com/s', params={'wd': '爸爸打我'}, headers=header)
with open('baidu.html', 'wb') as f:
f.write(res.content)# 响应体二进制内容
```
#### 2.3 使用urllib模块中文转码和编码
```bash
from urllib.parse import urlencode, unquote
# 把中文转成%的形式
res = urlencode({'wd': '我真帅'}, encoding='utf-8')
print(res)# wd=%E6%88%91%E7%9C%9F%E5%B8%85
# 把%形式转成中文
res = unquote('%E6%88%91%E7%9C%9F%E5%B8%85', encoding='utf-8')
print(res)# 我真帅
```
#### 2.4 带参数的GET请求请求头
>通常我们在发送请求时都需要带上请求头,请求头是将自身伪装成浏览器的关键,常见的有用的请求头如下
+ `user-agent`:客户端
+ `referer`:大型网站通常都会根据该参数判断请求的来源
+ `Cookie`:未认证的cookie,认证过的cookie
### 3.请求中带cookie
+ `cookie`经常用,作者把`cookies`当作一个参数使用
#### 3.1 方式一:存放在header(请求头)
```python
import requests
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36',
'cookie': 'Hm_lvt_b72418f3b1d81bbcf8f99e6eb5d4e0c3=1596202661; UM_distinctid=173a517b3192a1-07d51af695c35e-3a65420e-1fa400-173a517b31a70b;'
}
# 注意: url不要写错成了 'http://127.0.0.1:8050/index'
response = requests.get('http://127.0.0.1:8050/index/', headers=headers)
print(response.text)
# 服务端获取:
# 注意: 放在headers中, cookie对应的value如果有等于号, 那么等于号左边作为cookie的key, 右边作为cookie的value. 如果没有那么, key为空字符串. value为值.
# Dict or CookieJar:是一个对象,登录成功以后拿cookie得到的就是一个cookieJar对象
"""
{
'Hm_lvt_b72418f3b1d81bbcf8f99e6eb5d4e0c3': '1596202661',
'UM_distinctid': '173a517b3192a1-07d51af695c35e-3a65420e-1fa400-173a517b31a70b'
}
"""
```
#### 3.2 方式二:存放在指定的cookies参数中
```python
import requests
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36',
}
cookies = {
'cookie': 'Hm_lvt_b72418f3b1d81bbcf8f99e6eb5d4e0c3=1596202661; UM_distinctid=173a517b3192a1-07d51af695c35e-3a65420e-1fa400-173a517b31a70b;'
}
# 注意: url不要写错成了 'http://127.0.0.1:8050/index'
response = requests.get('http://127.0.0.1:8050/index/', headers=headers, cookies=cookies)
print(response.text)
# 服务端获取:
# 注意: cookies直接指定. 字典中的key对应的服务端cookie获取的key. 字典中value冒号分隔的等于号左边作为cookie的key, 右边作为value
'''
{
'cookie': 'Hm_lvt_b72418f3b1d81bbcf8f99e6eb5d4e0c3=1596202661',
'UM_distinctid': '173a517b3192a1-07d51af695c35e-3a65420e-1fa400-173a517b31a70b'
}
```
### 4.小结
```python
# headers参数:
1. 模拟浏览器: user-agent
2. 解决防盗链: referer
# 解决url编码问题
1. params参数默认解决url编码问题
2. urllib模块
# 携带cookie
第一种方式: 存放在headers中
客户端发送: {'cookie': 'key=value;key1=value1'}
服务端获取: {key: value, key1: value1}
第二种方式: 指定cookie参数 (提示: 可以存放dict 和 CookieJar对象)
客户端发送: {key: value, key1: value1}
服务端获取: {key: value, key1: value1}
response.text文本
response.content二进制
response.iter_content()迭代器
```
## 三、基于POST请求
### 1.携带数据发送POST请求
#### 1.1 携带数据:urlencoded
```python
import requests
response = requests.post('http://127.0.0.1:8050/index/', data={'name': 'shawn'})
print(response.text)
# 服务端获取
'''
request.body: b'name=shawn'
request.POST: <QueryDict: {'name': ['shawn']}>
'''
```
#### 1.2 携带数据:json
```python
import requests
response = requests.post('http://127.0.0.1:8050/index/', json={'name': 'shawn'})
print(response.text)
# 服务端获取
'''
request.body: b'{"name": "shawn"}'
request.POST: <QueryDict: {}>
'''
```
### 2.自动携带cookie
```bash
import requests
session = requests.session() # 注意: 是session()方法, 不是sessions()
session.post('http://127.0.0.1:8050/login/', json={'username': 'yang', 'password': '123'}) # 假设这个请求登录了
response = session.get('http://127.0.0.1:8050/index/')# 现在不需要手动带cookie, session会自动处理
print(response)
```
### 3.自定义请求头
```python
requests.post(url='xxxxxxxx',
data={'xxx': 'yyy'})# 没有指定请求头,# 默认的请求头:application/x-www-form-urlencoed
# 如果我们自定义请求头是application/json,并且用data传值, 则服务端取不到值
requests.post(url='',
data={'': 1, },
headers={
'content-type': 'application/json'
})
requests.post(url='',
json={'': 1, },
)# 默认的请求头:application/json
```
### 4.模拟登陆某网站
```bash
import requests
data = {
'username': '用户名',
'password': '密码',
'captcha': '9eee',
'ref': 'http://www.aa7a.cn/',
'act': 'act_login',
}
res = requests.post('http://www.aa7a.cn/user.php', data=data)
print(res.text)
# {"error":0,"ref":"http://www.aa7a.cn/"} 登录成功
# 取到cookie--》登录成功的cookie
# CookieJar 对象
print(res.cookies.get_dict())
res1 = requests.get('http://www.aa7a.cn/', cookies=res.cookies.get_dict())
print('用户名' in res1.text)
```
**如何携带data数据,如何携带cookies**
+ `cookies`:`CookieJar`或者字典
#### requests.session() 自动携带cookies
```python
import requests
# 拿到一个session对象,发送请求时,跟使用reqesuts一样,只不过它自动处理了cookie
session=requests.session()
data = {
'username': '用户名',
'password': '密码',
'captcha': '9eee',
'ref': 'http://www.aa7a.cn/',
'act': 'act_login',
}
res = session.post('http://www.aa7a.cn/user.php', data=data)
print(res.text)
# {"error":0,"ref":"http://www.aa7a.cn/"} 登录成功
# 取到cookie--》登录成功的cookie
# CookieJar 对象
print(res.cookies.get_dict())
res1 = session.get('http://www.aa7a.cn/')
print('用户名' in res1.text)
```
### 5.小结
```python
# 携带数据:
携带json数据: json={}
携带urlencoded数据: data={}
# 自动携带cookie:
session = requests.session()
res = session.post(认证url)
res1 = session.get(访问url)
# 自定义请求头:
默认: application/x-www-form-urlencoed
headers={'content-type': 'application/json'}
```
## 四、响应Response:requests模块响应对象
```python
# 1 响应对象
import requests
respone=requests.get('http://www.jianshu.com')
# # respone属性
print(respone.text) # 把body体中数据转成字符串格式
print(respone.content) # body体中的二进制格式
print(respone.status_code) # 响应状态码
print(respone.headers) # 响应头
print(respone.cookies) # 响应的cookie,如果登录了,这个cookie就是登录的cookie
print(respone.cookies.get_dict()) # cookiejar对象---》字典对象
print(respone.cookies.items()) # 跟字典一样
print(respone.url) # 请求的地址
print(respone.history) # 列表,访问一个网址,重定向了,列表中放这两个地址
print(respone.encoding) # 响应的编码格式(一般都是utf-8)
# 如果是图片,视频,保存到本地
# response.iter_content(): 可以循环它,而不是循环response.content,循环它一点点存
res=requests.get('xxx')
for line in res.iter_content():
f.write(line)
# 2编码问题(一般不存在,如果存在)
response.encoding='gb2312' # 改成网站编码方式即可
import requests
response=requests.get('http://www.autohome.com/news')
# response.encoding='gbk' #汽车之家网站返回的页面内容为gb2312编码的,而requests的默认编码为ISO-8859-1,如果不设置成gbk则中文乱码
print(response.text)
# 3 获取二进制内容
import requests
response=requests.get('https://wx4.sinaimg.cn/mw690/005Po8PKgy1gqmatpdmhij309j070dgj.jpg')
with open('a.jpg','wb') as f:
# f.write(response.content)
# 推荐用这个
for line in response.iter_content():
f.write(line)
# 4 json格式解码
import requests
import json
res = requests.get('https://api.luffycity.com/api/v1/course/actual/?category_id=1')
# print(json.loads(res.text))
print(res.json()['code'])
```
### 小结
```python
# response对象方法:
响应文本 response.text
响应二进制数据 response.content
响应状态码 response.status_code
响应头 response.headers
响应CookieJar对象 response.cookies
响应cookie字典 response.cookies.get_dict()
响应cookie列表套元组 response.cookies.items()
响应重定向之前的response对象 response.history
响应url地址 response.url
响应编码 response.encoding
响应数据的迭代器 response.iter_content()
# 解决响应内容编码:
手动: response.encoding = '你知道你获取url资源的编码'
自动: response.encoding = response.apparent_encoding
# 解析json:
1. json模块解析
json.loads(response.text)
2. requests提供的json()方法解析
response.json()
```
## 五、案例
### 案例一:爬取好看视频
分析出视频地址
```python
https://vd2.bdstatic.com/mda-mcbkh5a50wx55wpi/1080p/h264_cae/1620464746505493348/mda-mcbkh5a50wx55wpi.mp4
```
示例代码
```python
import requests
res = requests.get(
'https://vd2.bdstatic.com/mda-mcbkh5a50wx55wpi/1080p/h264_cae/1620464746505493348/mda-mcbkh5a50wx55wpi.mp4')
with open('study.mp4', 'wb') as f:
for line in res:
f.write(line)
```
### 案例二:爬取梨视频
分析出爬取视频的地址
```python
https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=9&start=0
```
示例代码
```python
import requests
import re
res = requests.get('https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=9&start=0')
# print(res.text)
video_ids = re.findall('<a href="(.*?)" class="vervideo-lilink actplay">', res.text)
# print(video_ids)
for video_id in video_ids:
video_url = 'https://www.pearvideo.com/' + video_id
# print(video_url)
real_video_id = video_id.split('_')[-1]
# print(real_video_id)
# print(video_url)
# res_detail=video_detail=requests.get(video_url)
# print(res_detail.text)
# break
# 直接发送ajax请求,拿到json格式数据--》json格式数据中就有mp4
header = {
# 解决跨域问题
'Referer': video_url
}
res_json = requests.get('https://www.pearvideo.com/videoStatus.jsp?contId=%s' % real_video_id, headers=header)
# print(res_json.json())
mp4_url = res_json.json()['videoInfo']['videos']['srcUrl']
mp4_url = mp4_url.replace(mp4_url.split('/')[-1].split('-'), 'cont-%s' % real_video_id)
print(mp4_url)
video_res = requests.get(mp4_url)
name=mp4_url.split('/')[-1]
with open('video/%s'%name, 'wb') as f:
for line in video_res.iter_content():
f.write(line)
# https://video.pearvideo.com/mp4/third/20210509/cont-1728918-15454898-094108-hd.mp4能播放
# https://video.pearvideo.com/mp4/third/20210509/1621312234758 -15454898-094108-hd.mp4
```
### 案例三:自动登录某网站
```python
import requests
# 拿到一个session对象,发送请求时,跟使用reqesuts一样,只不过它自动处理了cookie
session=requests.session()
data = {
'username': '用户名',
'password': '密码',
'captcha': '9eee',
'ref': 'http://www.aa7a.cn/',
'act': 'act_login',
}
res = session.post('http://www.aa7a.cn/user.php', data=data)
# print(res.text)
# {"error":0,"ref":"http://www.aa7a.cn/"} 登录成功
# 取到cookie--》登录成功的cookie
# CookieJar 对象
# print(res.cookies.get_dict())
res1 = session.get('http://www.aa7a.cn/')
print('用户名' in res1.text)
```
## 六、高级用法
### 1.SSL Cerf Verification(携带证书,很少见)
```python
import requests
response = requests.get('https://www.12306.cn', verify=False)
print(response.status_code)# 不验证证书,报警告,返回200
# 使用证书,需要手动携带
import requests
response = requests.get('https://www.12306.cn',
cert=('/path/server.crt',
'/path/key'))
print(response.status_code)
```
### 2.超时设置
```python
import requests
# 两种超时:float or tuple
# timeout = 0.001# 代表接收数据的超时时间
timeout = (0.0001, 0.002)# 0.1代表链接超时0.2代表接收数据的超时时间
response = requests.get('https://www.baidu.com',
timeout=timeout)
print(response.text)
print(response.status_code)
# 注意: 超时以后抛出异常.
'''
# 0.0001表示链接超时
requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.0001)
'''
```
### 3.认证设置
官网链接:http://docs.python-requests.org/en/master/user/authentication/
```python
'''
认证设置:登陆网站是,弹出一个框,要求你输入用户名密码(与alter很类似),此时是无法获取html的
但本质原理是拼接成请求头发送
r.headers['Authorization'] = _basic_auth_str(self.username, self.password)
一般的网站都不用默认的加密方式,都是自己写
那么我们就需要按照网站的加密方式,自己写一个类似于_basic_auth_str的方法
得到加密字符串后添加到请求头
r.headers['Authorization'] =func('.....')
'''
# 看一看默认的加密方式吧,通常网站都不会用默认的加密设置
import requests
from requests.auth import HTTPBasicAuth
r = requests.get('xxx', auth=HTTPBasicAuth('user', 'password'))
print(r.status_code)
# HTTPBasicAuth可以简写为如下格式
import requests
r = requests.get('xxx', auth=('user', 'password'))
print(r.status_code)
```
### 4.异常处理
```python
import requests
from requests.exceptions import *#可以查看requests.exceptions获取异常类型
try:
response = requests.get('https://www.baidu.com', timeout=(0.001, 0.002))
print(response.status_code)
except ReadTimeout:
print('读取超时!')
except ConnectionError: #网络不通
print('连接失败!')
except Timeout:
print('超时')
except RequestException:
print("请求异常")
except Exception as e:
print(e)
```
### 5.使用代{过}{滤}理
HTTP代{过}{滤}理| [百度百科链接](https://baike.baidu.com/item/http%E4%BB%A3%E7%90%86/7689519?fr=aladdin)
```python
'''
代{过}{滤}理:网上免费的(不稳定,自己玩)收费的(稳定,公司都会买)
代{过}{滤}理:高匿:隐藏访问者ip
透明:不隐藏访问者ip http的请求头中:X-Forwarded-For---》django中从META中取
每次访问,随机使用代{过}{滤}理
从网上找很多免费的代{过}{滤}理,放到列表中,每次随机取一个
使用第三方开源的代{过}{滤}理池:python+flask写的,自己搭建一个免费的代{过}{滤}理池https://github.com/jhao104/proxy_pool
'''
# 服务端
from django.shortcuts import HttpResponse
def test_ip(request):
ip = request.META.get('REMOTE_ADDR')
return HttpResponse(f'你的ip是{ip}')
def upload_file(request):
file = request.FILES.get('myfile')
with open(file.name, 'wb') as f:
for line in file:
f.write(line)
return HttpResponse()
urlpatterns = [
path('test_ip/', test_ip),
path('upload_file/', upload_file),
]
# 客户端
import requests
ip = requests.get('http://118.24.52.95:5010/get/').json()['proxy']
print(ip)
proxies = {
'http': ip
}
respone = requests.get('http://101.133.225.166:8088/test_ip/', proxies=proxies)
print(respone.text)
```
### 6.上传文件
```python
import requests
respone=requests.post('http://101.133.225.166:8088/upload_file/',files={'myfile':open('1 requests高级用法.py','rb')})
print(respone.text)
```
## 七、小结
```python
# SSL认证
verify=False不校验
verify=True校验.cert=(证书格式)
# 代{过}{滤}理
# HTTP代{过}{滤}理
proxies={'http': 'IP:PORT'}
# socks代{过}{滤}理: 安装requests
proxies={'http': 'socks://IP:PORT'}
# 超时设置
timeout=(连接超时时间, 接受数据超时时间)
抛出异常: ReadTimeOut
# 认证设置
from requests.auth import HTTPBasicAuth
auth=HTTPBasicAuth('user', 'password')
# 异常处理
from requests.exceptions import *
ReadTimeOut 连接 或者 获取数据超时
TimeOut 超时
ConnectionError 连接错误
RequestException请求异常
# 上传文件
files={key: file, key1: file1}
``` 出点py 处理 Excel数据的教程撒 坐等处理 excel 的文章,现在处理excel 确实比较需要 学习了,谢谢楼主分享 这不关注一波 十分不错,感谢python大佬 最近也在学习爬虫,这个文章写的很错。
请教一下,有些py模块方法看不懂,怎么办? 感谢分享 前来学习大佬文章 挺详细的,谢谢分享