zoukankan      html  css  js  c++  java
  • 测试之requests

    About

    环境:win10 + Python3.6 + PyCharm

    requests库是Python语言编写,基于urllib,采用Apache2 Licensed开源协议的HTTP库。

    它相对于urllib更加方便,大大节约了代码量,完全满足了HTTP测试相关需求。

    关于urllib:https://www.cnblogs.com/sundawei7/p/11953954.html

    安装

    pip install requests
    pip install -i https://pypi.doubanio.com/simple/ requests

    使用之前需引入。

    测试安装是否成功

    import requests   # 回车不报错就算安装成功
    response = requests.get("https://www.baidu.com")
    print(response.status_code)  # 200

    有网的情况下,返回了200表示安装成功。

    requests库的主要方法

    方法描述
    requests.request() 构造一个请求,支持以下各种方法
    requests.get() 获取html的主要方法
    requests.head() 获取html头部信息的主要方法
    requests.post() 向html网页提交post请求的方法
    requests.put() 向html网页提交put请求的方法
    requests.patch() 向html提交局部修改的请求
    requests.delete() 向html提交删除请求
    requests.Session() session相关

    我们一起来看看都是怎么玩儿的。

    requests.request()

    非常的重要!!!能用到的参数、基本都在这节展开。

    请求接受的参数

    requests.request(method, url, **kwargs)类能够构造一个请求,支持不同的请求方式。
    
    import requests
    
    response = requests.request(method='get', url='https://www.baidu.com')
    print(response.status_code)

    request类中来看看几个参数:

    • method:请求方式。
    • url:请求URL。
    • **kwargs:
      • params:字典或者字节序列,作为参数增加到url中,使用这个参数可以把一些键值对以k1=v1&k2=v2的模式增加到url中,get请求中用的较多。
      • data:字典、字节序列或者文件对象,重点作为向服务器提供或提交资源,作为请求的请求体,与params不同放在url上不同。它也可以接受一个字符串对象。
      • json:json格式的数据,可以向服务器提交json类型的数据。
      • headers:字典,定义请求的请求头,比如可以headers字典定义user agent。
      • cookies:字典或者CookieJar。
      • auth:元组,用来支持HTTP认证功能。
      • files:字典,用来向服务器传输文件。
      • timeout:指定超时时间。
      • proxies:字典,设置代理服务器。
      • allow_redirects:开关,是否允许对URL进行重定向,默认为True。
      • stream:开关,是否对获取内容进行立即下载,默认为False,也就是立即下载。这里需要说明的,stream一般应用于流式请求,比如说下载大文件,不可能一次请求就把整个文件都下载了,不现实,这种情况下,就要设置stream=True,requests无法将连接释放回连接池,除非下载完了所有数据,或者调用了response.close。
      • verify:开关,用于SSL证书认证,默认为True。
      • cert:用于设置保存本地SSL证书路径。

    流式请求,指的不是请求是流,而是请求返回的数据流,返回一点取一点,而普通的请求是返回完毕你再取内容。

    响应对象支持的属性

    import requests
    
    response = requests.request(method='get', url='http://www.httpbin.org/get')

    当一个请求被发送后,会有一个response响应。requests同样为这个response赋予了相关方法:

    • response:响应对象。
    • response.status_code:请求返回状态码。
    • response.text:字符串形式的响应内容。
    • response.json():返回响应的是json类型的数据,如果响应的类型不是json,则抛出ValueError
    • response.content:二进制的响应内容。
    • response.iter_content(chunk_size):生成器,在stream=True的情况下,当遍历生成器时,以块的形式返回,也就是一块一块的遍历要下载的内容。避免了遇到大文件一次性的将内容读取到内存中的弊端,如果stream=False,全部数据作为一个块返回。chunk_size参数指定块大小。
    • response.iter_lines():生成器,当stream=True时,迭代响应数据,每次一行,也就是一行一行的遍历要下载的内容。同样避免了大文件一次性写入到内存中的问题。当然,该方法不安全。至于为啥不安全,咱也不知道,咱也不敢问,主要是官网上没说!经查,如果多次调用该方法,iter_lines不保证重新进入时的安全性,因此可能会导致部分收到的数据丢失。
    • response.cookies:响应中的cookie信息。
    • response.cookies.get_dict():以字典的形式返回cookies信息。
    • response.cookies.items():以列表的形式返回cookies信息。
    • response.headers:响应头字典。取其中的指定key,response.headers.get('Content-Type', '哎呀,没取到!')
    • response.reqeust:请求类型。
    • response.url:请求的URL。
    • response.reason:响应HTTP状态的文本原因。
    • response.encoding:响应结果的编码方式。
    • response.encoding = “gbk”:修该响应编码方式,比如说响应结果的编码是utf-8,通过这么response.encoding = “gbk”指定为gbk。
    • response.apparent_encoding:根据响应字节流中去chardet库中匹配,返回编码方式,并不保证100%准确。
    • response.history:以列表的形式返回请求记录。列表内的请求以最老到最新排序。

    see also:https://www.cnblogs.com/sundawei7/p/11954129.html  http| https://www.cnblogs.com/sundawei7/p/11954195.html chardet

    requests.get()

    requests.get(url, params=None, **kwargs)发送GET请求。相关参数:

    • url,请求的URL。
    • params参数: 可选url中的额外参数,字典或者字节流格式。
    • **kwargs:参见requests.request中的kwargs。

    params参数

    get请求难免会带一些额外的参数K1=V1&K2=V2

    可以手动的拼接:

    import requests
    
    response = requests.get(url='http://www.httpbin.org/get?k1=v1&k2=v2')
    print(response.url)  # http://www.httpbin.org/get?k1=v1&k2=v2
    print(response.json().get('args'))  # {'k1': 'v1', 'k2': 'v2'}

    虽然没问题,但是稍显麻烦。

    现在,可以使用params参数来解决这个问题。

    import requests
    
    params = {"user": "张开", "pwd": "666"}
    response = requests.get(url='http://www.httpbin.org/get', params=params)
    print(response.url)  # http://www.httpbin.org/get?user=%E5%BC%A0%E5%BC%80&pwd=666
    print(response.json().get('args'))  # {'pwd': '666', 'user': '张开'}

    headers

    再来看,GET请求中如何携带headers。

    import requests
    headers = {"user-agent": UserAgent().random}
    response = requests.get(url='http://www.httpbin.org/get', headers=headers)
    print(response.json()['headers']['User-Agent'])  # Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5

    关于 fake_useragent:https://www.cnblogs.com/sundawei7/p/11954256.html

    cookies

    来看,GET请求中如何携带cookies。

    import requests
    from fake_useragent import UserAgent
    cookies = {
        "user": "zhangkai",
        "pwd": "666"
    }
    response = requests.get(url='http://www.httpbin.org/cookies', cookies=cookies)
    print(response.json())  # {'cookies': {'pwd': '666', 'user': 'zhangkai'}}
    因为url的返回值是json形式cookies也在里面,所以要去json中取,而不是从response.cookies取。

    再来看响应中的cookies:

    import requests
    
    url = 'http://www.baidu.com'
    response = requests.get(url=url)
    print(response.cookies)  # <RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
    print(response.cookies.get_dict())  # {'BDORZ': '27315'}
    print(response.cookies.items())  # [('BDORZ', '27315')]

    可以将response.cookies返回的是字典,它支持字典有关的方法。

    文件下载

    如果访问的是一个小文件,或者图片之类的,我们可以直接写入到本地就完了,也就是不用管stream,让它默认为False即可。

    来个美女图片提提神!

    import requests
    import webbrowser
    
    url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1568638318957&di=1d7f37e7caece1c39af05b624f42f0a7&imgtype=0&src=http%3A%2F%2Fimg3.duitang.com%2Fuploads%2Fitem%2F201501%2F17%2F20150117224236_vYFmL.jpeg'
    
    response = requests.get(url=url)
    f = open('a.jpeg', 'wb')
    f.write(response.content)
    f.close()
    webbrowser.open('a.jpeg')

    过瘾不?

    那要是下载大文件,可就不能这么干了:

    import requests
    import webbrowser
    
    
    url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1568638318957&di=1d7f37e7caece1c39af05b624f42f0a7&imgtype=0&src=http%3A%2F%2Fimg3.duitang.com%2Fuploads%2Fitem%2F201501%2F17%2F20150117224236_vYFmL.jpeg'
    
    response = requests.get(url=url, stream=True)
    with open('a.jpeg', 'wb') as f:
        for chunk in response.iter_content(chunk_size=256):
            f.write(chunk)
    webbrowser.open('a.jpeg')

    使用response.iter_content(chunk_size=256)一块一块下载,并且可以指定chunk_size大小。

    当然,也可以使用response.iter_lines一行一行遍历下载,但是官网说不安全,所以,忘掉它吧。

    requests.post()

    requests.post(url, data=None, json=None, **kwargs)发送POST请求,相关参数:

    • url:请求的URL。
    • data:可选参数,请求中携带表单编码的字典、bytes或者文件对象。
    • json:请求中携带json类型的数据。
    • **kwargs:参见requests.request中的kwargs。

    data参数

    import requests
    
    url = 'http://www.httpbin.org/post'
    # data为字典
    data_dict = {"k1": "v1"}
    response = requests.post(url=url, data=data_dict)
    print(response.json())
    
    # data为字符串
    data_str = "abc"
    response = requests.post(url=url, data=data_str)
    print(response.json(), type(response.json()['data']))
    
    # data为文件对象
    
    file = open('a.jpg', 'rb')
    response = requests.post(url=url, data=file)
    print(response.json())

    上述的基于data参数上传文件,不如使用专门的files参数来的合适。

    文件上传

    基于POST请求的文件上传,使用files参数。

    import requests
    file = {"file": open('a.jpg', 'rb')}
    response = requests.post('http://www.httpbin.org/post', files=file)
    print(response.json())

    json参数

    import requests
    
    url = 'http://www.httpbin.org/post'
    response = requests.post(url=url, json={"user": "zhangkai"})
    print(response.json())

    requests.head()

    requests.head(url, **kwargs)发送HEAD请求,相关参数:

    • url:请求URL。
    • **kwargs:参见requests.request中的kwargs。
    import requests
    
    url = 'http://httpbin.org/get'
    response = requests.head(url=url)
    print(response.headers)
    '''
    {
        'Access-Control-Allow-Credentials': 'true', 
        'Access-Control-Allow-Origin': '*', 
        'Content-Encoding': 'gzip', 
        'Content-Type': 'application/json', 
        'Date': 'Mon, 16 Sep 2019 10:58:07 GMT', 
        'Referrer-Policy': 'no-referrer-when-downgrade', 
        'Server': 'nginx', 
        'X-Content-Type-Options': 'nosniff', 
        'X-Frame-Options': 'DENY', 
        'X-XSS-Protection': '1; mode=block', 
        'Connection': 'keep-alive'
    }
    '''

    使用requests.head(url, **kwargs)的优点就是以较少的流量获得响应头信息,也可以用在分页中。

    requests.put()

    requests.put(url, data=None, **kwargs)发送PUT请求,相关参数:

    • url:请求URL。
    • data:可选参数,请求中携带表单编码的字典、bytes或者文件对象。
    • **kwargs:参见requests.request中的kwargs。
    import requests
    
    url = 'http://www.httpbin.org/put'
    data_dict = {"k1": "v1"}
    response = requests.put(url=url, data=data_dict)
    print(response.json())
    '''
    {
        'args': {}, 
        'data': '', 
        'files': {}, 
        'form': {'k1': 'v1'}, 
        'headers': {
            'Accept': '*/*', 
            'Accept-Encoding': 'gzip, deflate', 
            'Content-Length': '5', 
            'Content-Type': 'application/x-www-form-urlencoded', 
            'Host': 'www.httpbin.org', 
            'User-Agent': 'python-requests/2.19.1'
        }, 
        'json': None, 
        'origin': '1.202.184.14, 1.202.184.14', 
        'url': 'https://www.httpbin.org/put'
    }
    '''

    requests.patch()

    requests.patch(url, data=None, **kwargs)发送PATCH请求,相关参数:

    • url:请求URL。
    • data:可选参数,请求中携带表单编码的字典、bytes或者文件对象。
    • **kwargs:参见requests.request中的kwargs。
    import requests
    
    url = 'http://www.httpbin.org/patch'
    data_dict = {"k1": "v1"}
    response = requests.patch(url=url, data=data_dict)
    print(response.json())
    '''
    {   
        'args': {}, 
        'data': '', 
        'files': {}, 
        'form': {'k1': 'v1'}, 
        'headers': {
            'Accept': '*/*', 
            'Accept-Encoding': 'gzip, deflate', 
            'Content-Length': '5', 
            'Content-Type': 'application/x-www-form-urlencoded', 
            'Host': 'www.httpbin.org', 
            'User-Agent': 'python-requests/2.19.1'
        }, 
        'json': None, 
        'origin': '1.202.184.14, 1.202.184.14', 
        'url': 'https://www.httpbin.org/patch'
    }
    '''

    在requests中,PATCH请求和PUT类似。而区别:

    • PATCH是对PUT方法的补充,用来对已知资源进行局部跟新。
    • PATCH相比PUT更加节省带宽。

    requests.delete()

    requests.head(url, **kwargs)发送DELETE请求,相关参数:

    • url:请求URL。
    • **kwargs:参见requests.request中的kwargs。
    import requests
    
    test_url = 'https://api.github.com'
    
    def get_url(url):
        return '/'.join([test_url,url])
    
    email = '24xxxxx48@qq.com'
    
    def delete_email():
        r = requests.delete(get_url('user/emails'),json = email ,auth=('username','password'))
        print(r.status_code)
        print(r.text)
        print(r.request.headers)
    
    delete_email()

    将email,用户名,密码,换成自己的GitHub的。

    requests.Session()

    requests.Session()可以用来帮我们保持会话。

    import requests
    session = requests.Session()
    
    session.get('http://www.httpbin.org/cookies/set/username/root')
    response = session.get('http://www.httpbin.org/cookies')
    print(response.json())  # {'cookies': {'username': 'root'}}

    证书验证

    在之前,这个知识点还能拿12306网站举例的时候.....

    如果你请求的https协议的网址,那么人家网站首先会检测你的证书是否是合法的,如果不合法,会抛出SSLError。怎么处理呢。

    证书验证这里,有两种方式处理。第一种就是使用verify,是否进行证书校验,默认是True。我们选择不校验。

    import requests
    
    response = requests.get(url='https://www.12306.cn', verify=False)
    print(response.status_code)

    但有的时候,会有一个Warnning警告,建议你加证书验证。

    我们可以选择忽略这个警告:

    import requests
    from requests.packages import urllib3
    urllib3.disable_warnings()
    response = requests.get(url='https://www.12306.cn', verify=False)
    print(response.status_code)

    也可以选择提供一个CA证书:

    import requests
    
    response = requests.get(url='https://www.12306.cn', cert=('/path/server.crt', 'path/key'))
    print(response.status_code)

    很明显,没有什么CA证书,这就看个热闹吧。

    代理设置

    代理:就是访问一个网站,其实并不是你直接访问的,而是你发请求给A机器,A机器取请求B机器。B返回给A,A再返回给你。代理就是中间人的意思。为什么需要代理?因为:反爬虫网站一般使用IP来识别一个机器。老是一个IP在不停访问网站,该网站就会把这个IP拉入黑名单,不允许访问。这时,就需要很多IP再扰乱反爬虫工具的思维,避免封IP。

    普通代理

    import requests
    
    proxies = {
        "http": "http://10.10.1.10:3128",
        "https": "https://10.10.1.10:1080",
    }
    
    response = requests.get(url='https://www.12306.cn', proxies=proxies)
    print(response.status_code)

    代理需要用户名和密码

    import requests
    
    proxies = {
        "http": "http://user:password@10.10.1.10:3128",
    }
    response = requests.get(url='https://www.12306.cn', proxies=proxies)
    print(response.status_code)

    支持sock代理

    想要支持sock代理,那么首先要下载:

    pip install requests[socks]

    完事在用:

    import requests
    proxies = {
        'http': 'socks5://user:pass@host:port',
        'https': 'socks5://user:pass@host:port'
    }
    respone=requests.get('https://www.12306.cn',proxies=proxies)
    print(respone.status_code)

    超时

    超时,在规定的时间无响应。

    import requests
    respone=requests.get('https://www.12306.cn', timeout=0.0001)

    认证设置

    有些网站,会弹出一个提示框,要求你输入用户名和密码。

    import requests
    from requests.auth import HTTPBasicAuth
    
    response = requests.get(url='https://www.12306.cn', auth=HTTPBasicAuth(username='user', password='123'))
    print(response.status_code)

    HTTPBasicAuth的简写形式:

    import requests
    
    response = requests.get(url='https://www.12306.cn', auth=('user', '123'))
    print(response.status_code)

    异常处理

    异常处理相关异常类主要在requests.exceptions下,可以根据需求去翻看源码。

    import requests
    from requests.exceptions import ReadTimeout, ConnectionError, RequestException
    
    try:
        # RequestException
        # response = requests.get(url='https://www.12306.com')
    
        # ReadTimeout
        # response = requests.get(url='https://www.12306.cn', timeout=0.01)
    
        # ConnectionError ,断网演示...
        response = requests.get(url='https://xueqiu.com/stock/f10/finmainindex.json')
        # print(response.status_code)
    except ReadTimeout as e:
        print('ReadTimeout:', e)
    except ConnectionError as e:
        print('ConnectionError:', e)
    except RequestException as e:
        print('RequestException:', e)


    see also:Requests: 让 HTTP 服务人类 | https://www.cnblogs.com/linhaifeng/articles/7785043.html | https://2.python-requests.org//en/master/ | urllib | requests模块 - egon | python3 requests详解 | Python爬虫系列(三):requests高级耍法 | requests库入门08-delete请求

  • 相关阅读:
    The specified framework 'Microsoft.NETCore.App', version '1.0.1' was not found 解决办法
    docker registry push错误“server gave HTTP response to HTTPS client”
    windows server 2016安装docker
    Opserver 初探三《服务器数据监控》
    Opserver 初探二《exceptions配置》
    Opserver 初探一《Opserver的搭建》
    centos 7 免密登录
    nginx 入门配置
    php适配器模式
    进程和线程
  • 原文地址:https://www.cnblogs.com/sundawei7/p/11949153.html
Copyright © 2011-2022 走看看