美文网首页
python requests 大法 牛逼

python requests 大法 牛逼

作者: 天空蓝雨 | 来源:发表于2020-01-03 09:54 被阅读0次

    我忍了这个库好久了,都懒得总结,只会常用的结果方法。但是作为人类的结晶,作为python 众多模块的佼佼者,那就必须吃定她了
    github : star 40K+ (可以说很牛逼的存在了)

    • 5,923次 提交
    • 137个 发布
    • 553位 贡献者


      正如他的宣言:简单而优雅

    简单了解:

    >>> r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
    >>> r.status_code
    200
    >>> r.headers['content-type']
    'application/json; charset=utf8'
    >>> r.encoding
    'utf-8'
    >>> r.text
    u'{"type":"User"...'
    >>> r.json()
    {u'private_gists': 419, u'total_private_repos': 77, ...}
    
    
    ***********************************************************************
    简单说一下 urllib urllib2 urllib3 requests

    python2 里面有 urllib 和urllib2
    python3 把这两个合并为urllib
    而 urllib3 和requests 是第三方库,并且requests 是对urllib3 的封装

    回忆一下 ulrlib2 的使用方法(python2 中使用) 简单了解一下

    urllib2提供了Request该类,该类可以提供更多功能
    r = Request(url='http://www.mysite.com')
    r.add_header('User-Agent', 'awesome fetcher')
    r.add_data(urllib.urlencode({'foo': 'bar'})
    response = urlopen(r)
    # 请注意,urlencode()仅在urllib中,而不在urllib2中,因为 请求前肯定要是对url进行编码
    # urllib提供了urlencode方法,该方法用于生成GET查询字符串,而urllib2没有
    这种功能。这是urllib与urllib2经常一起使用的原因之一
    
    

    其实现在python3 整合了 urllib 和 urllib2 为 urllib (这里并不是 urllib3 因为urllib3 是第三方库)

    • urllib3

    Urllib3是一个功能强大,条理清晰,用于HTTP客户端的Python库。许多Python的原生系统已经开始使用urllib3。Urllib3提供了很多python标准库urllib里所没有的重要特性

    urllib3 简单使用(使用前先安装哦):

    pip install urllib3
    
    • 简单使用()
    >>> import urllib3
    >>> http = urllib3.PoolManager() # urllib3主要使用连接池进行网络请求的访
    # 问,所以访问之前我们需要创建一个连接池对象
    >>> r = http.request('GET', 'http://httpbin.org/robots.txt')
    >>> r.status
    200
    >>> r.data
    'User-agent: *\nDisallow: /deny\n'
    
    • 设置headers
    headers={'X-Something': 'value'}
    resp = http.request('GET', 'http://httpbin.org/headers', headers=headers)
    
    • 设置url参数
    fields = {'arg': 'value'}
    resp = http.request('GET', 'http://httpbin.org/get', fields=fields)
    

    如果使用的是POST等方法,则会将fields作为请求的请求正文发送
    也就是说 如果想用post 传url 参数,只能自己事先写好穿进去。

    • 设置代理
    >>> import urllib3
    >>> proxy = urllib3.ProxyManager('http://50.233.137.33:80', headers=
    {'connection': 'keep-alive'})
    >>> resp = proxy.request('get', 'http://httpbin.org/ip')
    >>> resp.status
    200
    >>> resp.data
    b'{"origin":"50.233.136.254"}\n'
    

    ***************************************************************

    讲完了urllib3
    下面切入正题 requests:

    • requests

    注:主要来自于官方文档 ,比较详细了

    • 快速入门

      请求:

    当然最常见的就是get 和 post 了

    r = requests.put('https://httpbin.org/put', data = {'key':'value'})
    r = requests.delete('https://httpbin.org/delete')
    r = requests.head('https://httpbin.org/get')
    r = requests.options('https://httpbin.org/get')
    r = requests.post('https://httpbin.org/post', data = {'key':'value'})
    r = requests.get('https://api.github.com/events')
    
    

    传递参数

    • params 参数:查询字符串的形式
      这个比较简单
      请求的url直接编写
      httpbin.org/get?key=val 像这样
      或者是传递参数
    payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
    r = requests.get('https://httpbin.org/get', params=payload)
    print(r.url)
    https://httpbin.org/get?key1=value1&key2=value2&key2=value3
    

    列表对应的参数会编码成统一个key,就是一个key 对应多个值的情况

    • data 参数:请求体传参,常见于post方式:
      请求体参数是传给 data 关键字参数
      字典将自动进行表单编码
    >>> payload = {'key1': 'value1', 'key2': 'value2'}
    >>> r = requests.post("https://httpbin.org/post", data=payload)
    >>> print(r.text)
    {
      ...
      "form": {
        "key2": "value2",
        "key1": "value1"
      },
      ...
    }
    

    对于data单键多值的情况,可以这样做
    这有时候特别有用
    1 、 创建data元组列表

    >>> payload_tuples = [('key1', 'value1'), ('key1', 'value2')]
    >>> r1 = requests.post('https://httpbin.org/post', data=payload_tuples)
    

    2 、 将列表作为值的字典

    >>> payload_dict = {'key1': ['value1', 'value2']}
    >>> r2 = requests.post('https://httpbin.org/post', data=payload_dict)
    

    上面两个传参的形式结果都是:

    >>> print(r1.text)
    {
      ...
      "form": {
        "key1": [
          "value1",
          "value2"
        ]
      },
      ...
    }
    >>> r1.text == r2.text
    True
    

    data 参数的格式
    其实可以直接发送string 格式的数据:

    >>> import json
    >>> url = 'https://api.github.com/some/endpoint'
    >>> payload = {'some': 'data'}
    >>> r = requests.post(url, data=json.dumps(payload))
    
    • json 参数:也算是请求体
      和data类似。但是会默认 把请求头参数 Content-Type设置为application/json
      注意:如果同时传入了data 或者 files,json 将成砖头,自动忽略掉
    • files 参数:上传文件
    >>> url = 'https://httpbin.org/post'
    >>> files = {'file': open('report.xls', 'rb')}
    
    >>> r = requests.post(url, files=files)
    >>> r.text
    {
      ...
      "files": {
        "file": "<censored...binary...data>"
      },
      ...
    }
    
    # 显式设置文件名,content_type和标头(这些就要用元祖传递了,顺序应该也是固定的哦)
    files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel',
     {'Expires': '0'})}
    然后传给request
    

    其实文件也可以是字符串啦:

    files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}.
    
    

    文件上传 流式传输
    requests 默认不支持流传输,但是官方推荐了另外一个包:
    但是有一个单独的软件包可以 requests-toolbelt。您应该阅读文档,以获取有关如何使用它的更多详细信息。

    • 请求头参数 headers

    headers 是一个dict
    后面再说

    >>> url = 'https://api.github.com/some/endpoint'
    >>> headers = {'user-agent': 'my-app/0.0.1'}
    
    >>> r = requests.get(url, headers=headers)
    

    响应:

    • 响应体:

      文本格式 r.text:

    默认编码格式设置为 响应头里面传过来的,当然你也可以在 .text 之前设置 自
    定义的编码格式:

    >>> r.encoding   # 获取编码格式
    'utf-8'
    >>> r.encoding = 'ISO-8859-1'  # 设置编码格式
    

    当你调用 .text 的时候,会动态读取当前的 r.encoding,然后返回响应数据unicode(字节码)对应的解码内容,是不是很人性化的
    其实 .text 内部 也是先运行 。content ,然后在进行解码的

    二进制格式 r.content:

    例如图片和zip等,最好用content ,便于后面写入文件操作

    >>> from PIL import Image
    >>> from io import BytesIO
    >>> i = Image.open(BytesIO(r.content))
    >>   i.show()  # 显示图片
     # Image.open我还记得,好像是图片对象,做毕设的时候好像用过
    

    json 格式 r.json():

    如果 json格式解码失败,报错:ValueError: No JSON object could be decoded
    其实这个方法也是调用内置的 json.loads() 。
    注意的是,有时候失败也会返回json 格式的字符串(例如HTTP 500的错误详细信息),所以这个不能是判断响应成功的根据。使用r.status_code 来判断更为确切啦啦啦

    原始套接字内容 r.raw (好像是个httpresponse 对象啊)

    但是有个前提 就是 请求的时候设置了 stream=True

    >>> r = requests.get('https://api.github.com/events', stream=True)
    >>> r.raw
    <urllib3.response.HTTPResponse object at 0x101194810>
    >>> r.raw.read(10)
    '\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'
    

    对于直接流传输的 r.iter_content 本地流式接收数据可以这样:

    with open(filename, 'wb') as fd:
        for chunk in r.iter_content(chunk_size=128):
            fd.write(chunk)
    

    r.iter_content vs r,raw
    iter_content 会自动解码gzip和deflate 传输编码,而raw 不会

    • 响应状态码 r.status_code

    >>> r.status_code
    200
    # 带有内置状态标记,防止你记不住折磨多状态码,那些是ok 的
    >>> r.status_code == requests.codes.ok
    True
    # 还有一个函数来抛出异常,这个就太细致了
    >>> bad_r.status_code
    404
    
    >>> bad_r.raise_for_status()
    Traceback (most recent call last):
      File "requests/models.py", line 832, in raise_for_status
        raise http_error
    requests.exceptions.HTTPError: 404 Client Error
    如果你的status_code  是200 这种,那就返回none
    >>> r.raise_for_status()
    None
    
    
    • 响应头 r.headers

    >>> r.headers
    {
        'content-encoding': 'gzip',
        'transfer-encoding': 'chunked',
        'connection': 'close',
        'server': 'nginx/1.0.4',
        'x-runtime': '148ms',
        'etag': '"e1ca502697e5c9317743dc078f67693f"',
        'content-type': 'application/json'
    }
    
    但是这个字典有点特殊

    r.headers['Content-Type'] 和 r.headers.get('content-type') 都能取到值

    • r.cookie

    >>> r.cookies['example_cookie_name']
    'example_cookie_value'
    

    要将自己的cookie发送到服务器,可以使用以下cookies 参数:

    >>> url = 'https://httpbin.org/cookies'
    >>> cookies = dict(cookies_are='working')
    
    >>> r = requests.get(url, cookies=cookies)
    >>> r.text
    '{"cookies": {"cookies_are": "working"}}'
    
    • 重定向和历史

    pass 吧

    • 超时

    指定的秒数后停止等待响应,这个以前没注意,现在看来是一个必传参数了。
    因为没有这个超时参数,有可能造成程序不停止:

    几乎所有生产代码都应在几乎所有请求中使用此参数。否则,可能会导致程序无限期挂起 ——官方的原话

    几秒钟timeout内未在基础套接字上接收到任何字节,则会引发异常timeout

    • 错误和异常

    网络问题(例如DNS故障,连接被拒绝等),请求将引发ConnectionError异常
    返回的状态码失败 则引发 HTTPError
    超时错误:Timeout则会引发异常
    请求超过配置的最大重定向数 : TooManyRedirects

    异常都继承自 requests.exceptions.RequestException

    至此,已经大致学习了,requests 最常见的内容

    高级用法

    :包含很多问题解决方法

    认证方式

    先把认证搞一下,高级教程,以后出问题的时候直接查询官方文档算了,因为东西实在是too much 了

    • 基本身份认证(就是用户名密码):

    >>> from requests.auth import HTTPBasicAuth
    >>> requests.get('https://api.github.com/user', auth=HTTPBasicAuth('user', 'pass'))
    <Response [200]>
    

    或者简写为:

    >> requests.get('https://api.github.com/user', auth=('user', 'pass'))
    <Response [200]>
    

    和上面的效果是一样的哦

    • netrc认证

    pass

    • 摘要式身份验证

    HTTP身份验证的另一种非常流行的形式是摘要身份验证,并且Requests也支持此功能

    >>> from requests.auth import HTTPDigestAuth
    >>> url = 'https://httpbin.org/digest-auth/auth/user/pass'
    >>> requests.get(url, auth=HTTPDigestAuth('user', 'pass'))
    <Response [200]>
    
    • OAuth 1身份验证

    OAuth是几种Web API的常见身份验证形式。该requests-oauthlib 库允许“请求”用户轻松进行OAuth 1身份验证的请求

    >>> import requests
    >>> from requests_oauthlib import OAuth1
    
    >>> url = 'https://api.twitter.com/1.1/account/verify_credentials.json'
    >>> auth = OAuth1('YOUR_APP_KEY', 'YOUR_APP_SECRET',
    ...               'USER_OAUTH_TOKEN', 'USER_OAUTH_TOKEN_SECRET')
    
    >>> requests.get(url, auth=auth)
    <Response [200]>
    
    • OAuth 2和OpenID Connect身份验证

    pass

    • 其他认证

    pass
    说实话,除了第一种用户名密码,其他的看不懂,哈哈哈

    *******************************************************

    这里附上 所有请求方式的方法都要调用的 request 方法(很像urllib3的
    urllib3.PoolManager().request(method,url,[...]))

    def request(method, url, **kwargs):
        """Constructs and sends a :class:`Request <Request>`.
    
        :param method: method for the new :class:`Request` object
        :param url: URL for the new :class:`Request` object.
        :param params: (optional) Dictionary, list of tuples or bytes to send
            in the body of the :class:`Request`.
        :param data: (optional) Dictionary, list of tuples, bytes, or file-like
            object to send in the body of the :class:`Request`.
        :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
        :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
        :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
        :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.
            ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``
            or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string
            defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers
            to add for the file.
        :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
        :param timeout: (optional) How many seconds to wait for the server to send data
            before giving up, as a float, or a :ref:`(connect timeout, read
            timeout) <timeouts>` tuple.
        :type timeout: float or tuple
        :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to 
    ``True``.
        :type allow_redirects: bool
        :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
        :param verify: (optional) Either a boolean, in which case it controls whether we verify
                the server's TLS certificate, or a string, in which case it must be a path
                to a CA bundle to use. Defaults to ``True``.
        :param stream: (optional) if ``False``, the response content will be immediately downloaded.
        :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
        :return: :class:`Response <Response>` object
        :rtype: requests.Response
    
        Usage::
    
          >>> import requests
          >>> req = requests.request('GET', 'https://httpbin.org/get')
          <Response [200]>
        """
    
        # By using the 'with' statement we are sure the session is closed, thus we
        # avoid leaving sockets open which can trigger a ResourceWarning in some
        # cases, and look like a memory leak in others.
        with sessions.Session() as session:
            return session.request(method=method, url=url, **kwargs)
    
    # requests.post  源码
    def post(url, data=None, json=None, **kwargs):
        r"""Sends a POST request.
    
        :param url: URL for the new :class:`Request` object.
        :param data: (optional) Dictionary, list of tuples, bytes, or file-like
            object to send in the body of the :class:`Request`.
        :param json: (optional) json data to send in the body of the :class:`Request`.
        :param \*\*kwargs: Optional arguments that ``request`` takes.
        :return: :class:`Response <Response>` object
        :rtype: requests.Response
        """
    
        return request('post', url, data=data, json=json, **kwargs)
    

    相关文章

      网友评论

          本文标题:python requests 大法 牛逼

          本文链接:https://www.haomeiwen.com/subject/pycmnctx.html