爬蟲-urllib3模塊的使用

urllib3是一個功能強大,對SAP健全的 HTTP客戶端,許多Python生態系統已經使用了urllib3。json

1、安裝

sudo pips install urllib3

2、建立PoolManager對象

  經過urllib3訪問網頁,首先須要構造一個PoolManager實例對象用於處理與線程池的鏈接以及線程安全的全部細節,而後經過request()方法來發送請求api

  • import urllib3
    
    #建立PoolManager對象,用於處理與線程池的鏈接以及線程安全的全部細節
    http = urllib3.PoolManager()
    
    #對須要爬取的網頁發送請求
    resp = http.request(method,url,...)

    method和url兩個參數必選,而且method須要大寫瀏覽器

3、基本GET請求(headers參數和fields參數)

  • 最基本的GET請求

    import urllib3
    
    #建立PoolManager對象,用於處理與線程池的鏈接以及線程安全的全部細節
    http = urllib3.PoolManager()
    
    #對須要爬取的網頁發送請求
    resp = http.request('GET','https://www.baidu.com/')
    
    print(resp.data.decode())#響應數據
    print(resp.headers)#響應頭信息
    print(resp.status)#狀態碼
    resp.release_conn()#釋放這個http鏈接
  • 添加headers和查詢參數

   能夠傳入headers參數(dict類型)來增長請求頭中的headers信息。能夠利用fields參數傳遞查詢參數(dict類型),注意url後面的'?‘必定不能帶上安全

  • import urllib3
    
    http = urllib3.PoolManager()
    
    kw = {"wd":"長城"}
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
    resp = proxy.request('GET','https://www.baidu.com/s',fields=kw,headers = headers)
    print(resp.data.decode())

4、基本POST請求(fields參數)

  • 最基本的POST請求須要傳入fields參數(dict類型),urllib3會自動將其轉換成表單數據類型

    import urllib3
    
    http = urllib3.PoolManager()
    
    #須要提交的數據
    data = {'word':'hello'}
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
    response = http.request('POST','http://httpbin.org/post',fields = data,headers = headers)
    print(response.data.decode())
  • url中攜帶查詢參數

    • 須要先經過urlencode()編碼,而後附加在url後面,這和GET方式有所不一樣(示例略)
  • 傳遞json數據(body參數)

    • 利用body參數進行傳遞,可是數據須要先序列化成json字符串,而後headers中須要設置'Content-Type':'application/json'
  • import urllib3
    import json
    
    http = urllib3.PoolManager()
    url = 'https://openapi.vmall.com/mcp/offlineshop/getShopList'
    data = {
    "portal":2,"lang":"zh-CN","country":"CN","brand":1,"province":"山西","city":"太原","pageNo":1,"pageSize":20
    }
    
    # 將字典類型數據序列化成json字符串
    json_data = json.dumps(data)
    
    #headers中設置Conten-Type爲application/json
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36',
        'Content-Type':'application/json'
    }
    resp = http.request('POST',url,body = json_data,headers = headers)
    print(resp.data.decode())

    注意:body參數和fields參數不能同時使用app

5、文件上傳

  • 普通文件上傳

    • 使用multipart/form-data編碼方式上傳文件,可使用和傳入Form data數據同樣的方法進行,並將文件定義爲一個二元元組(文件名,數據)或三元元組(文件名,數據,MIME類型),文件名的定義雖然不是嚴格要求的,可是推薦使用,以使得表現得更像瀏覽器
      import urllib3
      
      http = urllib3.PoolManager()
      
      #打開文件test.txt
      with open('test.txt','r') as f:
          file_data = f.read()
      
      headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
      
      #三元元組的方式傳入
      resp = http.request('POST','http://httpbin.org/post',fields={'filefield':('test.txt',file_data,'text/plain')},headers=headers)
      #二元元組的方式傳入
      #resp = http.request('POST','http://httpbin.org/post',fields={'filefield':('test.txt',file_data)},headers=headers)
      print(resp.data.decode('unicode_escape'))
  • 二進制文件上傳

    • 原始二進制數據,只要將其定義爲body參數便可。同時,建議對header的Content-Type參數進行設置
      import urllib3
      
      http = urllib3.PoolManager()
      
      with open('test.jpg','rb') as f:
          binary_data = f.read()
      headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",'Content-Type':'image/jpeg'}
      resp = http.request('POST','http://httpbin.org/post',body = binary_data,headers = headers)
      print(resp.data.decode())

6、超時設置

  • 使用timeout,能夠控制請求的總超時時間(鏈接超時和讀取超時時間總和),timeout參數爲一個浮點數:

    resp = http.request('GET','http://httpbin.org/delay/3',timeout = 4.0)
  • 也能夠分別設置總超時、鏈接超時和讀取超時時間,這時候須要使用Timeout()實例,裏面有3個關鍵字參數total,connect和read:

    #設置總超時時間爲3.0秒,鏈接超時不超過1.5秒,讀取超時不超過2.0秒
    resp = http.request('GET','http://httpbin.org/delay/3',timeout = urllib3.Timeout(total=3.0,connect=1.5,read=2.0))
  • 若是想讓全部的request都遵循一個timeout,能夠將timeout參數定義在PoolManager中,當在具體的request中再次定義timeout時,會覆蓋PoolManager層面上的timeout。

    http = urllib3.PoolManager(timeout = urllib3.Timeout(total=3.0,connect=1.5,read=2.0))
    
    #http = urllib3.PoolManager(timeout = 4.0)

7、重試(retries參數)以及重定向(redirect參數)設置

  • urllib3默認進行3次請求重試,3次重定向

  • 經過retries來自定義請求重試次數

    #設置請求重試次數10次
    resp = http.request('GET','http://httpbin.org/ip',retries = 10)
  • 將參數retries設爲False,請求重試和重定向會同時關閉

    #同時關閉請求重試和重定向
    resp = http.request('GET','http://httpbin.org/redirect/1',retries = False)
  • 將參數redirect設爲False,僅關閉重定向,保持請求重試

    #僅關閉重定向
    resp = http.request('GET','http://httpbin.org/redirect/1',redirect = False)
  • 經過Retry()實例能夠精細控制重試和重定向次數,該實例默認總重試次數爲10次,好比咱們設置3次重試,2次重定向

    resp = http.request('GET','http://httpbin.org/redirect/3',retries = urllib3.Retry(3,redirect = 2))
  • 若是想讓全部的request都遵循一個請求重試和重定向策略,能夠在PoolManager中定義retries參數,當在具體的request中再次定義retries時,會覆蓋 PoolManager層面上的retries。

    http = urllib3.PoolManager(retries = urllib3.Retry(3,redirect=2))
    #http = urllib3.PoolManager(retries = False)

8、ProxyManager(代理IP)

  • 若是你須要使用代理來訪問某個網站的話, 那麼你可使用 ProxyManager 對象來進行設置
  • ProxyManager和PoolManager的方法基本徹底相同,這裏舉個簡單的小例子
    import urllib3
    
    #建立ProxyManager對象
    proxy_http = urllib3.ProxyManager('https://175.42.122.96:9999')
    
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
    
    #利用代理對須要爬取的網頁發送請求
    resp = proxy_http.request('GET','https://www.baidu.com/',headers=headers)
    
    print(resp.data.decode())#響應數據
    print(resp.headers)#響應頭信息
    print(resp.status)#狀態碼
    resp.release_conn()#釋放這個http鏈接

9、SSL證書驗證

  • urllib3默認不驗證HTTPS請求,若是想開啓驗證,最可靠的方法是使用提供Mozilla根證書包的certifi包

    sudo pip3 install certifi
  • 得到證書後,能夠在PoolManager中定義cert_reqs參數和ca_certs參數,來自動處理證書驗證

    import urllib3
    import certici
    
    #開啓ssl證書自動驗證
    http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED',ca_certs=certifi.where())
    
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
    resp = http.request('GET','https://www.baidu.com/',headers=headers)
    
    print(resp.data.decode())
  • 若是須要,可使用OS提供的證書。只需指定證書包的完整路徑做爲ca_certs參數而不是 certifi.where()。例如,大多數Linux系統都存儲證書/etc/ssl/certs/ca-certificates.crt。

    import urllib3
    import certifi
    
    http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED',ca_certs='/etc/ssl/certs/ca-certificates.crt')
相關文章
相關標籤/搜索