每日一包 - requests

112 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

介绍

requests是Python内置的模块,可以帮助我们发送请求,从而实现使用代码控制请求发送。

基于get请求

  • 基本请求
import requests
​
response = requests.get('http://www.zzzfun.com/')
print(response.text)
  • 带参数的get请求

有些网站在请求头中需要携带user_agent,如果不携带的话就不会返回正常内容,比如:百度

import requests
​
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36}'}
​
response = requests.get('https://www.baidu.com/s?wd=python',
                        headers = header)
print(response.text)
  • 请求地址中携带params(两种方式,推荐第二种)

方式一:

res = requests.get('https://www.baidu.com/s?wd=美女',headers=header)

方式二:

response = requests.get('https://www.baidu.com/s',
                        headers = header,params={'wd':'漫画'})
print(response.url)  # https://www.baidu.com/s?wd=%E6%BC%AB%E7%94%BB

可以通过from urllib.parse import urlencode,unquote进行关键字的编码和解码

print(unquote('%E6%BC%AB%E7%94%BB'))  # 漫画
  • 带参数的get请求:cookies,两种方式

方式一:在header中放key=value的形式

header = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36',
    'cookie':'key=v1;key1=v2'
}
response = requests.get('http://127.0.0.1:8000/index/',headers=header)
print(response.text)

方式二:在header中放字典或者CookieJar对象

response=requests.get('http://127.0.0.1:8000/index/',headers=header,cookies={'name':'zhy','age':'18'})
# cookies中的key的值必须是字符串或者是bytes类型
print(response.text)

基于post请求

request.post()用法与request.get()用法完全一致,特殊的是requests.post()有一个data参数,用来存放请求体数据。

  • 默认请求头中的编码格式是application/x-www-form-urlencoed,需要使用data传值,否则服务端无法取到值
# 请求头默认编码格式,服务端无法在request.POST中取到数据
response = requests.post('http://127.0.0.1:8000/index/',json={'x':'y'})
​
​
# 请求头默认编码格式,服务端可以在request.POST中取到数据
response = requests.post('http://127.0.0.1:8000/index/',data={'x':'y'})
  • 请求头可以自定义编码格式application/json,服务端可以在request.post中获取到数据
# 在服务端中获取的数据是b'{"age": 1}'
response = requests.post('http://127.0.0.1:8000/index/',json={'x':'y'})
# 在服务端获取到的数据是b'age=1'
response = requests.post('http://127.0.0.1:8000/index/',data={'x':'y'})

自动携带cookie

session=requests.session()
res=session.post('http://127.0.0.1:8000/index/')  # 假设这个请求登录了
res1=session.get('http://127.0.0.1:8000/order/')  # 现在不需要手动带cookie,session会帮咱处理

response对象

response=requests.post('http://127.0.0.1:8000/index/',data={'name':'lqz'})
print(response.text)  # 响应的文本
print(response.content)  # 响应体的二进制
print(response.status_code)  # 响应状态码
print(response.headers)    # 响应头
print(response.cookies)   # cookie
print(response.cookies.get_dict()) #  把cookie转成字典
print(response.cookies.items())  # key和value
print(response.url)        # 请求的url
print(response.history)   #[]放重定向之前的地址
print(response.encoding)  # 响应的编码方式
​
​
# 写入文件
response.iter_content()  # 获取二进制流:图片,视频,大文件,一点一点循环取出来
with open('a','wb') as f:
    for line in response.iter_content():
        f.write(line)

编码问题

import requests
response=requests.get('http://www.autohome.com/news')
# response.encoding='gbk' #汽车之家网站返回的页面内容为gb2312编码的,而requests的默认编码为ISO-8859-1,如果不设置成gbk则中文乱码
print(response.text)

解析json

import json
respone=requests.post('http://127.0.0.1:8000/index/',data={'name':'lqz'})
print(type(respone.text))  # 响应的文本
print(json.loads(respone.text))
print(respone.json())  # 相当于上面那句话
print(type(respone.json()))  # 相当于上面那句话

高级用法---ssl

#证书验证(大部分网站都是https)
import requests
respone=requests.get('https://www.12306.cn') #如果是ssl请求,首先检查证书是否合法,不合法则报错,程序终端
​
​
#改进1:去掉报错,但是会报警告
import requests
respone=requests.get('https://www.12306.cn',verify=False) #不验证证书,报警告,返回200
print(respone.status_code)
​
​
#改进2:去掉报错,并且去掉警报信息
import requests
from requests.packages import urllib3
urllib3.disable_warnings() #关闭警告
respone=requests.get('https://www.12306.cn',verify=False)
print(respone.status_code)
​
#改进3:加上证书
#很多网站都是https,但是不用证书也可以访问,大多数情况都是可以携带也可以不携带证书
#知乎\百度等都是可带可不带
#有硬性要求的,则必须带,比如对于定向的用户,拿到证书后才有权限访问某个特定网站
import requests
respone=requests.get('https://www.12306.cn',
                     cert=('/path/server.crt',
                           '/path/key'))
print(respone.status_code)

高级用法---使用代理

respone=requests.get('http://127.0.0.1:8000/index/',proxies={'http':'代理的地址和端口号',})

代理:免费代理,收费代理花钱买

代理池:列表放了一堆代理ip,每次随机取一个,再发请求就不会封ip了

高匿和透明代理?如果使用高匿代理,后端无论如何拿不到你的ip,使用透明,后端能够拿到你的ip。

后端如何拿到透明代理的ip, 后端:X-Forwarded-For

超时设置

#超时设置
#两种超时:float or tuple
#timeout=0.1 #代表接收数据的超时时间
#timeout=(0.1,0.2)#0.1代表链接超时  0.2代表接收数据的超时时间
​
import requests
respone=requests.get('https://www.baidu.com',
                     timeout=0.0001)

认证设置(比较古老)

import requests
r=requests.get('xxx',auth=('user','password'))
print(r.status_code)

异常处理

import requests
from requests.exceptions import * #可以查看requests.exceptions获取异常类型try:
   r=requests.get('http://www.baidu.com',timeout=0.00001)
except ReadTimeout:
    print('===:')
except Exception as e:
    print(e)

上传文件

res=requests.post('http://127.0.0.1:8000/index/',files={'files':open('fox.jpg','rb')})
print(res.text)

模拟登陆网站:www.aa7a.cn/

import requests
session = requests.session()
data = {
    'username': '1280135234@qq.com',
    'password': 'zhuang1026',
    'captcha': 2222,
    'remember': 1,
    'ref': 'http://www.aa7a.cn/user.php?act=logout',
    'act': 'act_login',
}
res = session.post('http://www.aa7a.cn/user.php',data=data)
print(res.text)
​
cookie = res.cookies
print(cookie)
​
result = session.get('http://www.aa7a.cn/index.php')
print('1280135234@qq.com' in result.text)

爬取梨视频

import requests
import re
​
# 点击加载更多会发送ajax请求,打开network得到请求的地址
res = requests.get('https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=9&start=0')
​
# print(res.text)
# 每次加载12个视频,每个视频对应一个li标签,通过正则匹配得到a标签内的网址
re_video = '<a href="(.*?)" class="vervideo-lilink actplay">'
video_urls = re.findall(re_video,res.text)
for video in video_urls:
    url = 'https://www.pearvideo.com/'+video
    res_video = requests.get(url)
    # print(res_video.text)
    # break
    re_video_mp4 = 'hdflvUrl="",sdflvUrl="",hdUrl="",sdUrl="",ldUrl="",srcUrl="(.*?)",vdoUrl=srcUrl,skinRes="//www.pearvideo.com/domain/skin",videoCDN="//video.pearvideo.com";'
    video_url = re.findall(re_video_mp4,res_video.text)[0]
    # print(video_url)
    res_video_content = requests.get(video_url)
    video_name = video_url.rsplit('/',1)[-1]
    with open(video_name,'wb') as f:
        for line in res_video_content.iter_content():
            f.write(line)