• python requests模块


    简介

    Requests是用python语言基于urllib编写的,采用的是Apache2 Licensed开源协议的HTTP库,Requests它会比urllib更加方便,可以节约我们大量的工作。

    安装

    pip快速安装

    pip3 install requests
    

    使用

    先上一串代码

    response.text返回的是Unicode格式,通常需要转换为utf-8格式,否则就是乱码。response.content是二进制模式,可以下载视频之类的,如果想看的话需要decode成utf-8格式。
    不管是通过response.content.decode("utf-8)的方式还是通过response.encoding="utf-8"的方式都可以避免乱码的问题发生

    import requests
    response = requests.get("https://www.baidu.com")
    print(type(response))
    print(response.status_code)
    print(type(response.text))
    
    response.encoding = "utf-8"
    print(response.text)
    print(response.cookies)
    print(response.content)
    print(response.content.decode("utf-8"))
    

    请求方式

    HTTP请求的方法:
    HTTP/1.1协议中共定义了八种方法(有时也叫“动作”),来表明Request-URL指定的资源不同的操作方式。
    HTTP1.0定义了三种请求方法:GET, POST 和 HEAD方法。
    HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法

    • 1.OPTIONS
      返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性。
    • 2.HEAD
      向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。
    • 3.GET
      向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在Web Application中,其中一个原因是GET可能会被网络蜘蛛等随意访问。Loadrunner中对应get请求函数:web_link和web_url
    • 4.POST
      向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 Loadrunner中对应POST请求函数:web_submit_data,web_submit_form
    • 5.PUT
      向指定资源位置上传其最新内容。
    • 6.DELETE
      请求服务器删除Request-URL所标识的资源。
    • 7.TRACE
      回显服务器收到的请求,主要用于测试或诊断。
    • 8.CONNECT
      HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

    注意:
    1)方法名称是区分大小写的,当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Mothod Not Allowed);当服务器不认识或者不支持对应的请求方法时,应返回状态码501(Not Implemented)。
    2)HTTP服务器至少应该实现GET和HEAD/POST方法,其他方法都是可选的,此外除上述方法,特定的HTTP服务器支持扩展自定义的方法。

    import requests
    r1 = requests.post("http://httpbin.org/post")
    r2 = requests.put("http://httpbin.org/put")
    r3 = requests.delete("http://httpbin.org/delete")
    r4 = requests.head("http://httpbin.org/get")
    r5 = requests.options("http://httpbin.org/get")
    
    print(r1)
    print(r2)
    print(r3)
    print(r4)
    print(r5)
    
    基本Get
    import requests
    url = 'https://www.baidu.com'
    response = requests.get(url)
    print(response.text)
    

     

    带参数的GET请求

    如果想查询http://httpbin.org/get页面的具体参数,需要在url里面加上,例如我想看有没有Host=httpbin.org这条数据,url形式应该是http://httpbin.org/get?Host=httpbin.org

    下面提交的数据是往这个地址传送data里面的数据。

    import requests
    url = 'http://httpbin.org/get'
    
    data = {
       'name':'zhangsan',
       'age':'25'
    }
    
    response = requests.get(url,params=data)
    print(response.url)
    print(response.text)
    
    json数据

    从下面的数据中我们可以得出,如果结果:
    requests中response.json()方法等同于json.loads(response.text)方法。

    import requests
    import json
    
    response = requests.get("http://httpbin.org/get")
    print(type(response.text))
    print(response.text)
    print(response.json())
    print(json.loads(response.text))
    print(type(response.json()))
    
    添加header
    import requests
    url = 'https://www.zhihu.com/'
    
    headers = {
         'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'
    }
    response = requests.get(url,headers=headers)
    print(response.text)
    
    基本post请求

    通过post把数据提交到url地址,等同于以字典的形式提交form表单里面的数据。

    import requests
    url = 'https://httpbin.org/post'
    data = {
       'name':'jack',
       'age':'23'
    }
    response = requests.post(url,data=data)
    print(response.text)
    

    执行结果:

    {
      "args": {},
      "data": "",
      "files": {},
      "form": {
        "age": "23",
        "name": "jack"
      },
      "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "Content-Length": "16",
        "Content-Type": "application/x-www-form-urlencoded",
        "Host": "httpbin.org",
        "User-Agent": "python-requests/2.24.0",
        "X-Amzn-Trace-Id": "Root=1-61386488-14f223f6476ba61903060b45"
      },
      "json": null,
      "origin": "101.230.216.177",
      "url": "https://httpbin.org/post"
    }
    
    响应
    import requests
    
    response = requests.get("http://www.baidu.com")
    # 打印请求页面的状态码
    print(type(response.status_code),response.status_code)
    # 打印请求网址的headers所有信息
    print(type(response.headers),response.headers)
    # 打印请求网址的cookies信息
    print(type(response.cookies),response.cookies)
    # 打印请求网址的地址
    print(type(response.url),response.url)
    # 打印请求的历史记录(以列表的形式显示)
    print(type(response.history),response.history)
    

    执行结果:

    <class 'int'> 200
    <class 'requests.structures.CaseInsensitiveDict'> {'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform', 
    'Connection': 'keep-alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Date': 'Wed, 08 Sep 2021 07:27:36 GMT', 'Last-Modified': 'Mon, 23 Jan 2017 13:27:36 GMT', 'Pragma': 'no-cache', 'Server': 'bfe/1.0.8.18', 'Set-Cookie': 'BDORZ=27315; max-age=86400; domain=.baidu.com; path=/', 'Transfer-Encoding': 'chunked'}
    <class 'requests.cookies.RequestsCookieJar'> <RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
    <class 'str'> http://www.baidu.com/
    <class 'list'> []
    

    内置状态码

    100: ('continue',),
    101: ('switching_protocols',),
    102: ('processing',),
    103: ('checkpoint',),
    122: ('uri_too_long', 'request_uri_too_long'),
    200: ('ok', 'okay', 'all_ok', 'all_okay', 'all_good', '\o/', '✓'),
    201: ('created',),
    202: ('accepted',),
    203: ('non_authoritative_info', 'non_authoritative_information'),
    204: ('no_content',),
    205: ('reset_content', 'reset'),
    206: ('partial_content', 'partial'),
    207: ('multi_status', 'multiple_status', 'multi_stati', 'multiple_stati'),
    208: ('already_reported',),
    226: ('im_used',),
    
    # Redirection.重定向
    300: ('multiple_choices',),
    301: ('moved_permanently', 'moved', '\o-'),
    302: ('found',),
    303: ('see_other', 'other'),
    304: ('not_modified',),
    305: ('use_proxy',),
    306: ('switch_proxy',),
    307: ('temporary_redirect', 'temporary_moved', 'temporary'),
    308: ('permanent_redirect',
          'resume_incomplete', 'resume',), # These 2 to be removed in 3.0
    
    # Client Error.客户端错误
    400: ('bad_request', 'bad'),
    401: ('unauthorized',),
    402: ('payment_required', 'payment'),
    403: ('forbidden',),
    404: ('not_found', '-o-'),
    405: ('method_not_allowed', 'not_allowed'),
    406: ('not_acceptable',),
    407: ('proxy_authentication_required', 'proxy_auth', 'proxy_authentication'),
    408: ('request_timeout', 'timeout'),
    409: ('conflict',),
    410: ('gone',),
    411: ('length_required',),
    412: ('precondition_failed', 'precondition'),
    413: ('request_entity_too_large',),
    414: ('request_uri_too_large',),
    415: ('unsupported_media_type', 'unsupported_media', 'media_type'),
    416: ('requested_range_not_satisfiable', 'requested_range', 'range_not_satisfiable'),
    417: ('expectation_failed',),
    418: ('im_a_teapot', 'teapot', 'i_am_a_teapot'),
    421: ('misdirected_request',),
    422: ('unprocessable_entity', 'unprocessable'),
    423: ('locked',),
    424: ('failed_dependency', 'dependency'),
    425: ('unordered_collection', 'unordered'),
    426: ('upgrade_required', 'upgrade'),
    428: ('precondition_required', 'precondition'),
    429: ('too_many_requests', 'too_many'),
    431: ('header_fields_too_large', 'fields_too_large'),
    444: ('no_response', 'none'),
    449: ('retry_with', 'retry'),
    450: ('blocked_by_windows_parental_controls', 'parental_controls'),
    451: ('unavailable_for_legal_reasons', 'legal_reasons'),
    499: ('client_closed_request',),
    
    # Server Error.服务端错误
    500: ('internal_server_error', 'server_error', '/o\', '✗'),
    501: ('not_implemented',),
    502: ('bad_gateway',),
    503: ('service_unavailable', 'unavailable'),
    504: ('gateway_timeout',),
    505: ('http_version_not_supported', 'http_version'),
    506: ('variant_also_negotiates',),
    507: ('insufficient_storage',),
    509: ('bandwidth_limit_exceeded', 'bandwidth'),
    510: ('not_extended',),
    511: ('network_authentication_required', 'network_auth', 'network_authentication'),
    
    import requests
    response = requests.get('http://www.jianshu.com/404.html')
    # 使用requests内置的字母判断状态码
    # 如果response返回的状态码是非正常的就返回404错误
    if response.status_code != requests.codes.ok:
      print('404')
    # 如果页面返回的状态码是200,就打印下面的状态
    response = requests.get('https://www.baidu.com')
    if response.status_code == 200:
       print('200')
    

    执行结果:

    404
    200
    

    requests的高级操作

    文件上传
    import requests
    url = "http://httpbin.org/post"
    files = {"files":open("test.jpg","rb")}
    response = requests.post(url,files=files)
    print(response.text)
    
    获取cookie
    import requests
    response = requests.get('https://www.baidu.com')
    print(response.cookies)
    
    for key,value in response.cookies.items():
       print(key,'==',value)
    

    执行结果:

    <RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
    BDORZ == 27315
    

    cookie与session的区别

    简易版:

    • 1.session在服务器端,cookie 在客户端(浏览器)
    • 2.session默认被存在在服务器的一个文件里(不是内存)
    • 3.session的运行依赖session id,而session id是存在cookie中的,也就是说,如果浏览器禁用了cookie,同时,session也会失效(但是可以通过其它方式实现,比如在url中传递session_id)
    • 4.session可以放在文件、数据库、或内存中都可以。
    • 5.用户验证这种场合一般会用session。因此,维持一个会话的核心就是客户端的唯一标识,即session id。

    详细版:

    • 1.由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放 Session。
    • 2.思考一下服务端如何识别特定的客户?这个时候Cookie就登场了。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。有人问,如果客户端的浏览器禁用了 Cookie 怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。
    • 3.Cookie其实还可以用在一些方便用户的场景下,设想你某次登陆过一个网站,下次登录的时候不想再次输入账号了,怎么办?这个信息可以写到Cookie里面,访问网站的时候,网站页面的脚本可以读取这个信息,就自动帮你把用户名给填了,能够方便一下用户。这也是Cookie名称的由来,给用户的一点甜头。
    • 4.总结一下:Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;
      Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。

    http是无状态协议

    无状态是指,当浏览器给服务器发送请求的时候,服务器响应客户端请求。但是当同一个浏览器再次发送请求给服务器的时候,服务器并不知道他就是刚才的那个浏览器。简单的说,就是服务器不会去记得你,所以就是http的无状态协议。

    会话维持

    cookie的一个作用就是可以用于模拟登陆,做会话维持。

    import requests
    session = requests.session()
    session.get('http://httpbin.org/cookies/set/number/123456')
    response = session.get('http://httpbin.org/cookies')
    print(response.text)
    

    执行结果:

    {
      "cookies": {
        "number": "123456"
      }
    }
    

    证书验证

    无证书访问
    import requests
    response = requests.get('https://www.12306.cn')
    # 在请求https时,requests会进行证书的验证,如果验证失败则会抛出异常
    print(response.status_code)
    
    关闭证书验证
    import requests
    # 关闭验证,但是仍然会报出证书警告
    response = requests.get('https://www.12306.cn',verify=False)
    print(response.status_code)
    
    消除验证证书的警报
    import requests
    from requests.packages import urllib3
    
    urllib3.disable_warnings()
    response = requests.get('https://www.12306.cn',verify=False)
    print(response.status_code)
    

    手动设置证书

    import requests
    # 证书路径,写真实的
    response = requests.get('https://www.12306.cn',cert=('/path/server.crt','/path/key'))
    print(response.status_code)
    

    代理设置

    设置普通代理
    import requests
    proxies = {
       "http":"http://127.0.0.1:9743",
       "https":"https://127.0.0.1:9743",
    }
    response = requests.get("https://www.taobao.com",proxies=proxies)
    print(response.status_code)
    
    设置用户名和密码代理
    import requests
    proxies = {
       "http": "http://user:password@127.0.0.1:9743",
    }
    response = requests.get("https://www.taobao.com",proxies=proxies)
    print(response.status_code)
    

    超时时间

    通过timeout参数可以设置超时的时间

    import requests
    from requests.exceptions import ReadTimeout
    
    try:
        # 设置必须在500ms内收到响应,不然或抛出ReadTimeout异常
        response = requests.get("http://httpbin.org/get",timeout=0.5)
        print(response.status_code)
    except ReadTimeout:
       print('timeout')
    
    认证设置

    通过碰到需要认证的网站可以通过requests.auth模块实现

    import requests
    from requests.auth import HTTPBasicAuth
    # 方法一:
    # r = requests.get('http://120.27.34.24:9001', auth=HTTPBasicAuth('user','123'))
    # 方法二:
    r = requests.get('http://120.27.34.24:9001',auth=('user','123'))
    print(r.status_code)
    
    异常处理

    关于reqeusts的异常在这里可以看到详细内容:http://www.python-requests.org/en/master/api/#exceptions
    所有的异常都是在requests.excepitons中。

    从源码我们可以看出
    RequestException继承IOError,
    HTTPError,ConnectionError,Timeout继承RequestionException
    ProxyError,SSLError继承ConnectionError
    ReadTimeout继承Timeout异常
    这里列举了一些常用的异常继承关系,详细的可以看:
    http://cn.python-requests.org/zh_CN/latest/_modules/requests/exceptions.html#RequestException
    通过下面的例子进行简单的演示:

    import requests
    from requests.exceptions import ReadTimeout,ConnectionError,RequestException
    try:
       response = requests.get("http://httpbin.org/get",timeout=0.5)
       print(response.status_code)
    except ReadTimeout:
       print('Timeout')
    except ConnectionError:
       print('Connection error')
    except RequestException:
       print('Error')
    

    首先被捕捉的异常是timeout,当把网络断掉的haul就会捕捉到ConnectionError,如果前面异常都没有捕捉到,最后也可以通过RequestExctption捕捉到。

  • 相关阅读:
    Reverse Nodes in k-Group [LeetCode]
    Text Justification [LeetCode]
    Path Sum [LeetCode]
    Multiply Strings [LeetCode]
    Populating Next Right Pointers in Each Node II [Leetcode]
    013 集合
    012 元组
    02 isdecimal(), isdigit(), isnumeric()
    011 字符串的内置方法 三
    010 字符串的内置方法 二
  • 原文地址:https://www.cnblogs.com/even160941/p/15244110.html
Copyright © 2020-2023  润新知