<input id="ohw05"></input>
  • <table id="ohw05"><menu id="ohw05"></menu></table>
  • <var id="ohw05"></var>
  • <code id="ohw05"><cite id="ohw05"></cite></code>
    <label id="ohw05"></label>
    <var id="ohw05"></var>
  • Python之Requests模塊

    Requests 支持 Python 2.6—2.7以及3.3—3.7

    官方文檔:https://docs.python-requests.org/zh_CN/latest/

    發送請求

    首先需要導入模塊:

    import requests
    

    get請求

    url = r'http://httpbin.org/get'
    r= requests.get(url=url)
    

    帶參數的get請求

    向url傳遞參數,如:httpbin.org/get?key=val,可使用params關鍵字參數(字典)。

    url = r'http://httpbin.org/get'
    payload1 = {'key1':'aaa','key2':'bbb'}
    payload2 = {'key1':'aaa','key2':['bbb','ccc']}
    
    r1= requests.get(url=url,params=payload1)
    r2= requests.get(url=url,params=payload2)
    

    打印該url,可見url已被正確編碼:

    >>> print(r1.url)
    http://httpbin.org/get?key1=aaa&key2=bbb
    >>> print(r2.url)
    http://httpbin.org/get?key1=aaa&key2=bbb&key2=ccc
    

    注意字典里值為 None 的鍵都不會被添加到 URL 的查詢字符串里。

    post請求

    基礎用法:

    url = r'http://httpbin.org/post'
    data = {'key':'value'}
    r = requests.post(url=url,data=data)			# data參數為關鍵字參數,不賦值也可
    

    data參數

    傳入字典dict數據

    發送表單形式的數據(類似html表單),只需要傳遞一個dictdata關鍵字參數。

    數據字典在requests發出請求時會被自動編碼為表單形式。

    url= r'https://httpbin.org/post'
    data = {'key1':'aaa','keys':'bbb'}
    r = requests.post(url=url,data=data)
    print(r.text)
    

    輸出:

    {
      ...
      "form": {
        "key1": "aaa",
        "key2": "bbb"
      },
      ...
    }
    

    字典的值可以為列表:

    url= r'https://httpbin.org/post'
    data = {'key1':'aaa','keys':['bbb','ccc']}
    r = requests.post(url=url,data=data)
    print(r.text)
    

    輸出:

    {
      ...
      "form": {
        "key1": "aaa",
        "keys": [
          "bbb",
          "ccc"
        ]
      },
      ...
    }
    

    傳遞列表list、元組tuple的數據:

    以下集幾種數據類型,效果相同。

    data = {'key1':'aaa','key2':['bbb','ccc']}
    
    data = [['key1','aaa'],['key2','bbb'],['key2','ccc']]
    
    data = (('key1','aaa'),('key2','bbb'),('key2','ccc'))
    

    傳遞字符串string數據

    傳遞字符串數據,將不會被編碼為表單形式,而是直接發布出去。

    url= r'https://httpbin.org/post'
    data = r"{'key1':'aaa','keys':'bbb'}"
    r = requests.post(url=url,data=data)
    print(r.text)
    

    輸出:

    {
      ...
      "data": "{'key1':'aaa','keys':'bbb'}",
      "form": {},
      "json": null,
      ...
    }
    

    傳遞json字符串

    傳遞json字符串,需要先將python數據編碼為json字符串

    url= r'https://httpbin.org/post'
    data = {'key1':'aaa','keys':'bbb'}
    r = requests.post(url=url,data=json.dumps(data))			# json.dumps()方法,將python數據類型轉換成json字符串,需要import json
    print(r.text)
    

    輸出:

    {
      ...
      "data": "{\"key1\": \"aaa\", \"keys\": \"bbb\"}",
      "form": {},
      "json": {
        "key1": "aaa",
        "keys": "bbb"
      },
      ...
    }
    

    json參數

    發送json形式的數據,只需要傳遞一個dictjson關鍵字參數。

    dict數據在requests發出請求時會被自動編碼為json形式。

    url= r'https://httpbin.org/post'
    data = {'key1':'aaa','keys':'bbb'}
    r = requests.post(url=url,json=data)
    print(r.text)
    

    輸出:

    {
      ...
      "data": "{\"key1\": \"aaa\", \"keys\": \"bbb\"}",
      "form": {},
      "json": {
        "key1": "aaa",
        "keys": "bbb"
      },
      ...
    }
    

    從輸出可見,效果同傳入json字符串給data一樣。

    files參數上傳文件

    Requests 使得上傳多部分編碼(Multipart-Encoded)文件變得很簡單

    url= r'https://httpbin.org/post'
    with open(file='study_requests/numbers.csv',mode='rb') as f:			# 二進制文件,mode='rb'
        files = {'file':f,}
        r = requests.post(url=url,files=files)
    print(r.text)
    

    輸出:

    {
      ...
      "files": {
        "file": "1,2,3,4\na,b,c,d\n"
      },
      ...
    }
    

    也可以發送作為文件來接收的字符串:

    url= r'https://httpbin.org/post'
    files = {'file':('report.csv','1,2,3,4\n,a,b,c,d')}
    r = requests.post(url=url,files=files)
    

    可以顯式地設置文件名,文件類型和請求頭(下面是官網示例代碼):

    >>> url = 'http://httpbin.org/post'
    >>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
    
    >>> r = requests.post(url, files=files)
    >>> r.text
    {
      ...
      "files": {
        "file": "<censored...binary...data>"
      },
      ...
    }
    

    建議用二進制模式(binary mode)打開文件。這是因為 Requests 可能會試圖為你提供 Content-Length header,在它這樣做的時候,這個值會被設為文件的字節數(bytes)。如果用文本模式(text mode)打開文件,就可能會發生錯誤。

    如果你發送一個非常大的文件作為 multipart/form-data 請求,你可能希望將請求做成數據流。默認下 requests 不支持, 但有個第三方包 requests-toolbelt 是支持的。你可以閱讀 toolbelt 文檔來了解使用方法。

    流式上傳

    Requests支持流式上傳,這允許你發送大的數據流或文件而無需先把它們讀入內存。

    要使用流式上傳,僅需為你的請求體提供一個類文件對象即可:

    with open('massive-body','rb') as f:
        requests.post('http://some.url/streamed', data=f)
    

    上傳多個文件

    可以在一個請求中發送多個文件。只要把文件設到一個元組的列表中,其中元組結構為 (form_field_name, file_info)

    例如,假設你要上傳多個圖像文件到一個 HTML 表單,使用一個多文件 field 叫做 "images":

    <input type="file" name="images" multiple="true" required="true"/>
    

    代碼:

    >>> url = 'http://httpbin.org/post'
    >>> multiple_files = [
            ('images', ('foo.png', open('foo.png', 'rb'), 'image/png')),
            ('images', ('bar.png', open('bar.png', 'rb'), 'image/png'))]
    >>> r = requests.post(url, files=multiple_files)
    >>> r.text
    {
      ...
      'files': {'images': 'data:image/png;base64,iVBORw ....'}
      'Content-Type': 'multipart/form-data; boundary=3131623adb2043caaeb5538cc7aa0b3a',
      ...
    }
    

    其它請求

    >>> r = requests.put('http://httpbin.org/put', data = {'key':'value'})
    >>> r = requests.delete('http://httpbin.org/delete')
    >>> r = requests.head('http://httpbin.org/get')
    >>> r = requests.options('http://httpbin.org/get')
    

    獲取響應

    Requests會自動解碼來自服務器的響應內容,包括被gzip壓縮的格式。

    r.encoding,響應的編碼,Requests會基于 HTTP 頭部對響應的編碼作出有根據的推測。可對其賦值。Requests將以新值對r.text重新編碼。

    r.rext,文本形式的響應內容,自動根據響應頭部的字符編碼進行解碼。當你訪問 r.text 之時,Requests 會使用r.encoding對其編碼。

    r.content,字節形式(二進制)的響應內容。會自動解碼 gzip 和 deflate 壓縮。

    r.json(),json格式的響應內容,字典類型。requests內置的json解碼器,調用失敗將拋出異常,調用成功也不意味著響應成功(有的服務器會在失敗的響應中包含一個 JSON 對象(比如 HTTP 500 的錯誤細節)。所以最好使用 r.raise_for_status() 或者檢查 r.status_code 是否和你的期望相同。

    r.raw,原始套接字響應,必須在初始請求中設置 stream=True

    r.status_code,響應狀態碼。為方便引用,Requests還附帶了一個內置的狀態碼查詢對象requests.codes.ok

    >>> r.status_code == requests.codes.ok
    True
    

    r.raise_for_status(),請求失敗時,拋出異常。請求正常時,返回None

    下面的代碼將展示r.textr.contentr.json()的效果:

    url = r'https://httpbin.org/get'
    r = requests.get(url=url)
    
    print(r.url, end='\n-------------\n')
    print(r.encoding, end='\n-------------\n')
    print(r.text, end='\n-------------\n')
    print(r.content, end='\n-------------\n')
    print(r.json(), end='\n-------------\n')
    print(type(r.json()))
    

    輸出:

    https://httpbin.org/get
    -------------
    utf-8
    -------------
    {
      "args": {},
      "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "Host": "httpbin.org",
        "User-Agent": "python-requests/2.26.0",
        "X-Amzn-Trace-Id": "Root=1-61d11e2d-43e8d7612c24f5075f3c902e"
      },
      "origin": "58.39.97.213",
      "url": "https://httpbin.org/get"
    }
    
    -------------
    b'{\n  "args": {}, \n  "headers": {\n    "Accept": "*/*", \n    "Accept-Encoding": "gzip, deflate", \n    "Host": "httpbin.org", \n    "User-Agent": "python-requests/2.26.0", \n    "X-Amzn-Trace-Id": "Root=1-61d11e2d-43e8d7612c24f5075f3c902e"\n  }, \n  "origin": "58.39.97.213", \n  "url": "https://httpbin.org/get"\n}\n'       
    -------------
    {'args': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.26.0', 'X-Amzn-Trace-Id': 'Root=1-61d11e2d-43e8d7612c24f5075f3c902e'}, 'origin': '58.39.97.213', 'url': 'https://httpbin.org/get'}
    -------------
    <class 'dict'>
    

    r.raw最大的作用是流下載,這里不說明了,可查閱官網。

    獲取請求頭和響應頭

    r.headers,服務器響應頭,字典形式。

    r.requests.headers,發送到服務器的請求頭,字典形式。

    url = r'https://httpbin.org/get'
    r = requests.get(url=url)
    print('請求頭:\n', r.request.headers)
    print('響應頭:\n', r.headers)
    

    輸出:

    請求頭:
     {'User-Agent': 'python-requests/2.26.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
    響應頭:
     {'Date': 'Sun, 02 Jan 2022 06:36:20 GMT', 'Content-Type': 'application/json', 'Content-Length': '306', 'Connection': 'keep-alive', 'Server': 'gunicorn/19.9.0', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': 'true'}
    

    可以使用任意大小寫形式來訪問這些頭字段:

    >>> r.headers['Content-Type']
    'application/json'
    >>> r.headers.get('content-type')
    'application/json'
    >>> r.request.headers['User-Agent']
    'python-requests/2.26.0'
    

    添加請求頭

    給請求添加HTTP頭部信息,只需要傳遞一個dictheaders關鍵字參數即可。

    r.request.headers,查看發送請求的頭部信息。

    url = r'https://httpbin.org/get'
    headers = {'user-agent':'my-app/0.0.1'}
    r = requests.get(url=url,headers=headers)
    print(r.request.headers)
    

    輸出:

    {'user-agent': 'my-app/0.0.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
    

    注意: 定制 header 的優先級低于某些特定的信息源,例如:

    • 如果在 .netrc 中設置了用戶認證信息,使用 headers= 設置的授權就不會生效。而如果設置了 auth= 參數,.netrc 的設置就無效了。
    • 如果被重定向到別的主機,授權 header 就會被刪除。
    • 代理授權 header 會被 URL 中提供的代理身份覆蓋掉。
    • 在我們能判斷內容長度的情況下,header 的 Content-Length 會被改寫。

    更進一步講,Requests 不會基于定制 header 的具體情況改變自己的行為。只不過在最后的請求中,所有的 header 信息都會被傳遞進去。

    獲取響應中的cookie:

    r.cookies可以獲取響應中的cookie,前提是響應中包含

    >>> url = 'http://example.com/some/cookie/setting/url'
    >>> r = requests.get(url)
    
    >>> r.cookies['example_cookie_name']
    'example_cookie_value'
    

    發送cookies到服務器

    可以傳遞一個dictcookies 參數:

    url = r'https://httpbin.org/cookies'
    cookies = {'cookies_1':'working'}
    
    r = requests.get(url=url,cookies=cookies)
    print(r.text)
    print(r.cookies)
    print(r.cookies.get('cookies_1'))
    print(r.cookies['cookies_1'])
    

    輸出:

    {
      "cookies": {
        "cookies_1": "working"
      }
    }
    
    <RequestsCookieJar[]>			# Cookie 的返回對象為 RequestsCookieJar,它的行為和字典類似
    None
    Traceback (most recent call last):
      File "d:/software/VSCode/Project_study/study_requests/study_requests.py", line 59, in <module>
        print(r.cookies['cookies_1'])
      File "C:\Users\10282787\.virtualenvs\Project_study-Zg5dkSCc\lib\site-packages\requests\cookies.py", line 328, in __getitem__
        return self._find_no_duplicates(name)
      File "C:\Users\10282787\.virtualenvs\Project_study-Zg5dkSCc\lib\site-packages\requests\cookies.py", line 399, in _find_no_duplicates
        raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path))
    KeyError: "name='cookies_1', domain=None, path=None"
    

    Cookie 的返回對象為 RequestsCookieJar,它的行為和字典類似,但接口更為完整,適合跨域名跨路徑使用。你還可以把 Cookie Jar 傳到 Requests 中:

    >>> jar = requests.cookies.RequestsCookieJar()
    >>> jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
    >>> jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
    >>> url = 'http://httpbin.org/cookies'
    >>> r = requests.get(url, cookies=jar)
    >>> r.text
    '{"cookies": {"tasty_cookie": "yum"}}'
    

    重定向和請求歷史

    默認情況下,除了 HEAD, Requests 會自動處理所有重定向。

    • HEAD方法,可以設置allow_redirects=True啟用重定向;
    • GET、POST、OPTIONS、PUT、PATCH 或者 DELETE,可以設置allow_redirects=False禁用重定向;

    可以使用響應對象的 r.history 方法來追蹤重定向,它是一個 Response 對象的列表,按照從最老到最近的請求進行排序。

    >>> r = requests.get('http://github.com')
    >>> r.url
    'https://github.com/'
    >>> r.status_code
    200
    >>> r.history
    [<Response [301]>]
    

    超時

    可以設置requests請求方法的timeout參數,超過設定的秒數時間之后停止等待響應。

    建議所有代碼均設置該參數,否則程序可能永遠失去響應。

    url = r'http://www.httpbin.org'
    r = requests.get(url=url,timeout=0.01)
    

    異常:

    Traceback (most recent call last):
        File "d:/software/VSCode/Project_study/study_requests/study_requests.py", line 45, in <module>
            r = requests.get(url=url,timeout=0.01)
        ...
    requests.exceptions.ConnectTimeout: HTTPConnectionPool(host='www.httpbin.org', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x0000015C0428A430>, 'Connection to www.httpbin.org timed out. (connect timeout=0.01)'))
    

    注意:

    timeout 僅對連接過程有效,與響應體的下載無關。 timeout 并不是整個下載響應的時間限制,而是如果服務器在 timeout 秒內沒有應答,將會引發一個異常(更精確地說,是在timeout 秒內沒有從基礎套接字上接收到任何字節的數據時)If no timeout is specified explicitly, requests do not time out.

    錯誤與異常

    遇到網絡問題(如:DNS 查詢失敗、拒絕連接等)時,Requests 會拋出一個 ConnectionError 異常。

    如果 HTTP 請求返回了不成功的狀態碼(請求失敗), Response.raise_for_status() 會拋出一個 HTTPError異常。

    請求超時,則拋出一個 Timeout 異常。

    若請求超過了設定的最大重定向次數,則會拋出一個 TooManyRedirects 異常。

    所有Requests顯式拋出的異常都繼承自 requests.exceptions.RequestException

    解決SSL證書問題

    參考:https://www.jianshu.com/p/d715df88a5ef

    requests庫支持.crt和.key證書

    requests庫支持這兩種證書

    import requests
    
    url = r'https://www.example.com/path'
    resp = requests.post(url=url, data='payload', cert=('example.crt', 'example.key'), verify=False)  # 若需要對響應包進行驗證,則需要給 verify 傳參
    

    requests-pkcs12庫支持pfx證書

    pfs證書,可使用requests-pkcs12庫

    文檔:https://www.cnpython.com/pypi/requests-pkcs12

    在擁有 .pfx 文件和其密碼(若有加密)的前提下進行 https 請求。

    獲取到請求后, 響應的使用方法和requests一樣:

    import requests
    import requests_pkcs12
    url = r'https://www.example.com/path'
    resp = requests_pkcs12.post(url=url, pkcs12_filename=r'D:/tmp/client/aaa/client.pfx', pkcs12_password='123456', verify=False)
    print(resp.status_code)
    print(resp.text)
    
    posted @ 2022-02-04 21:39  wuenwuen  閱讀(50)  評論(0編輯  收藏  舉報
    国产美女a做受大片观看