zoukankan      html  css  js  c++  java
  • interface--requests封装

    前言

    1. requests 继承了urllib2的所有特性
    2. requests 支持HTTP连接保持和连接池,支持保持会话,支持文件上传,支持自动确定响应内容的编码,支持国际化的 URL 和 POST 数据自动编码
    3. 使用 requests 发送网络请求非常简单
    4. requests 中文手册

    安装

    pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple

    request特性

    get & post 请求

    import requests
    
    def http_request(method, url, data=None, header=None):
        r = requests.request(method=method, url=url, data=data, headers=header)
        return r
    
    if __name__ == '__main__':
        # get请求
        resp1 = http_request('get', 'https://www.wanandroid.com/project/tree/json')
        print(f'get请求结果:
    {resp1.json()}')
    
        # post请求
        data = {'username': 'xiaobai', 'password': '123456'}
        resp2 = http_request('post', 'https://www.wanandroid.com/user/login', data=data)
        print(f'post请求结果:
    {resp2.json()}')
    

    查看响应结果

    import requests
    
    def http_request(method, url, data=None, header=None, proxies=None):
        r = requests.request(method=method, url=url, data=data, headers=header, proxies=proxies)
        return r
    
    if __name__ == '__main__':
        # get请求
        resp1 = http_request('get', 'https://www.wanandroid.com/project/tree/json')
        # 获取json数据(如果响应结果为json格式,否则报错)
        print(resp1.json())
        
        # 获取字节流数据,即被编码的进制数据,解码用.decode('utf-8'),如果响应结果中存在图片音视频等文件,且需要获取这些数据,则使用此种获取响应结果的方式
        # print(resp1.content)
        
        # 获取Unicode格式的数据,即str数据
        # print(resp1.text)
        
        # 查看字符串编码
        print(resp1.encoding)
        # 查看完整URL
        print(resp1.url)
        # 查看响应状态码
        print(resp1.status_code)
    

    执行结果(json数据太长,只截取部分结果)

    get & post 请求区别

    1. get 请求是从服务器获取数据,在request中,使用params='get_param'传参,源码解释如下
      :param params: (optional) Dictionary, list of tuples or bytes to send in the query string for the :class:Request.
    2. post 请求是从服务器发送数据,在request中,使用data='post_param'传参,源码解释如下
      :param data: (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the :class:Request.
    3. 其它关于安全性方面的区别这里不作赘述...

    代理配置proxies

    • 在测试调试过程中,可能需要发送的请求能够被抓取,可以将抓包工具设置为中间代理的方式去实现,request中使用proxies实现:
    proxies = {"http": "http://127.0.0.1:8888", "https": "https://127.0.0.1:8888"}
    resp1 = http_request('get', 'https://www.wanandroid.com/project/tree/json', proxies=proxies)
    print(resp1.status_code)
    
    • 在此测试中,只有启用代理服务器(域名为http://127.0.0.1:8888),get请求才能成功(还是调用上一部分http_request()方法)

    https请求客户端ssl证书认证问题

    1. 证书认证是个很麻烦的问题,requesrs默认启用ssl证书认证,verify=True,但很多网站证书不可能一致,则会报SSLerror错误,使用verify=False跳过认证即可
    2. 但认证跳过会仍会告警InsecureRequestWarning,未经认证的HTTPS请求,但这个警告并不影响你执行request请求,如需禁用,使用 urllib3 来忽略掉这个警告,如下:
    import urllib3
    import requests
    
    def http_request(method, url, data=None, header=None, proxies=None, verify=False):
        urllib3.disable_warnings()  # 忽略浏览器认证警告
        r = requests.request(method=method, url=url, data=data, headers=header, proxies=proxies, verify=verify)
        return r
    if __name__ == '__main__':
        resp1 = http_request('get', 'https://www.wanandroid.com/project/tree/json')
        print(resp1.status_code)
    

    再次执行

    cookies

    获取Cookies参数

    import requests
    
    r = requests.get("http://www.baidu.com/")
    # 返回Cookiejar对象:
    cookiejar = r.cookies
    # 将CookieJar转为字典:
    cookiedict = requests.utils.dict_from_cookiejar(cookiejar)
    
    print(cookiejar)
    print(cookiedict)
    

    执行结果

    session

    1. session 是 requests 中非常重要的对象,代表从客户端浏览器连接服务器开始,到客户端浏览器与服务器断开
    2. 会话能让我们在跨请求时候保持某些参数,比如 cookie,使所有操作都不需要重新获取cookie,比如登录后,使用session会话获取订单,不再需要登录
    3. 简单示例:
    import requests
    
    # 创建session对象
    s = requests.session()
    r = s.request('get', 'https://www.wanandroid.com/project/tree/json')
    print(r.json())
    

    重新封装request

    需求

    1. 需要在调用request时,即保持同一级会话
    2. 调用request时,可以自动判断get 和 post请求,并作出不同的响应
    3. 遇到异常可以抛出
    4. 接口响应超时后,能够自动重运行
    5. 可以选择代理服务器执行脚本
    6. 忽略掉证书认证
    7. 格式化输出json字符串

    代码实现

    很明显,request库不能实现上述功能,需再次封装,如下:

    # File  : run_main.py
    # IDE   : PyCharm
    
    import json
    import urllib3
    import requests
    import warnings
    from common.logger import Logger
    from requests.adapters import HTTPAdapter
    
    class RunMain:
    
        def __init__(self):
            self.logging = Logger().logger
    
        def run_main(self, method, url, data=None, proxies=None, headers=None, timeout=15, max_retries=3):
            '''
            :param url: tested url
            :param data: dict type
            :param method: 'get' or 'post'
            :param proxies: The result is displayed in fiddler:
            {"http": "http://127.0.0.1:8888", "https": "https://127.0.0.1:8888"}
            :param timeout: 请求默认超时时间15s
            :param max_retries: 请求超时后默认重试3次
            '''
            s = requests.session()
            s.mount('http://', HTTPAdapter(max_retries=max_retries))
            s.mount('https://', HTTPAdapter(max_retries=max_retries))
            urllib3.disable_warnings()  # 忽略浏览器认证警告
            warnings.simplefilter('ignore', ResourceWarning)    # 忽略 ResourceWarning(https认证)警告
            if method.upper() == 'POST':
                try:
                    res = s.request(method='post', url=url, data=data, verify=False, proxies=proxies, headers=headers, timeout=timeout)
                except Exception as e:
                    self.logging.error('POST请求出错,错误信息为:{0}'.format(e))
            elif method.upper() == 'GET':
                try:
                    res = s.request(method='get', url=url, params=data, verify=False, proxies=proxies, headers=headers, timeout=timeout)
                except Exception as e:
                    self.logging.error('GET请求出错,错误信息为:{0}'.format(e))
            else:
                raise ValueError('method方法为get和post')
            self.logging.info(f'请求方法:{method},请求路径:{url}, 请求参数:{data}, 请求头:{headers}')
    
            # json.dumps() 将 dict 格式化字符串
            # ensure_ascii=False 禁止中文编码为 ascii,indent 缩进,sort_keys 排序
            # json.loads() 将 str 转换为 dict
            if isinstance(res.text, str):
                try:
                    json_data = json.loads(res.text)
                    finally_data = json.dumps(json_data, ensure_ascii=False, indent=2, sort_keys=True)
                except ValueError as e:
                    self.logging.error('数据类型错误,错误信息为:{0}'.format(e))
                    raise e
            else:
                finally_data = res.text
    
            return finally_data
    
    
    if __name__ == '__main__':
        method = 'get'
        url = 'https://www.wanandroid.com//hotkey/json'
        response = RunMain().run_main(method, url)
        print(response)
    
    

    执行结果(截取部分,可以自己运行脚本)

  • 相关阅读:
    Apache Hadoop 3.0.0 Release Notes
    控制你的数据,你才能得到有效且高效的数据结果
    读写分离与主从同步数据一致性
    代理ip proxy
    maximize_window fullscreen_window minimize_window
    HTTP 代理原理及实现
    browser user agent
    res_d_l =[{'contents':d.contents,'href':d.attrs['href']} for d in rd] 泛型
    tmp
    Connection reset by peer
  • 原文地址:https://www.cnblogs.com/xiaohuboke/p/13640092.html
Copyright © 2011-2022 走看看