1. 程式人生 > >Urllib庫和URLError庫的異常處理

Urllib庫和URLError庫的異常處理

Urllib 庫是 Python 一個用於操作 URL 的模組, Python3 中合併了 Python2.X 中的 Urllib2 和 Urllib 庫,成為 Urllib 庫

通過Urllib爬取網頁

import urllib.request

file=urllib.request.urlopen("http://www.baidu.com")
data=file.read()
dataline=file.readline()
#print(dataline)
#print(data)

fhandle=open("D:/1.html","wb")
fhandle.write(data)
fhandle.close
() filname=urllib.request.urlretrieve("http://www.baidu.com",filename="D:/2.html") urllib.request.urlcleanup() print(file.info)

file.read() 讀取檔案的全部內容 返回字串變數
file.readlines() 全部內容 返回列表變數,讀取全文推薦這種方式
file.readline() 讀取檔案的一行內容

urlretrieve() 函式可以直接把網頁下載到本地目錄,目錄要提前建好

模擬瀏覽器

Urllib 的 urlopen() 函式不支援一些 HTTP 的高階功能,修改報頭一般用以下兩個函式:
1. urllib.request.build_opener()
2. urllib.request.add_header()

urllib.request.build_opener() :

設定好字典 headers={‘xxx’:’yyyy’}

opener=urllib.request.build_opener() #建立自定義opener物件
opener.addheaders=[headers] # 設定好頭資訊
data=opener.open(url).read()
urllib.request.add_header() :
req=urllib.request.Request(url) #建立 Request 物件
req.add_header('欄位名':'欄位值'
) #設定報頭 data=urllib.request.urlopen(req).read()

代理伺服器設定:

import urllib.request


def use_proxy(proxy_addr, url):
    kv = {
        'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Mobile Safari/537.36'}
    kv = urllib.parse.urlencode(kv).encode('utf-8') #轉碼

    proxy = urllib.request.ProxyHandler({'http': proxy_addr})
    opener = urllib.request.build_opener(proxy, urllib.request.HTTPHandler)
    urllib.request.install_opener(opener)

    data = urllib.request.urlopen(url, data=kv).read().decode('utf-8')
    return data

proxy_addr = '某個代理地址'
url = 'http://www.baidu.com'
data = use_proxy(proxy_addr, url)
print(data[-50:])

注意報頭轉換為 utf-8
以及代理伺服器的設定

第一個引數為代理資訊,第二個引數為 urllib.request.HTTPHandler 類

proxy = urllib.request.ProxyHandler({'http': proxy_addr}) #設定代理資訊
opener = urllib.request.build_opener(proxy, urllib.request.HTTPHandler) 
urllib.request.install_opener(opener)

DebugLog 實戰

沒什麼好說的,列印除錯日誌
設定好引數,還是要建立 opener 物件

#邊爬邊列印debuglog
import urllib.request
httphd=urllib.request.HTTPHandler(debuglevel=1)
httpshd=urllib.request.HTTPSHandler(debuglevel=1)
opener=urllib.request.build_opener(httphd,httpshd)
urllib.request.install_opener(opener)
data=urllib.request.urlopen('http://www.baidu.com')
print(data.read()[-50:])

URLError 實戰

產生 URLError 的原因主要有:

  1. 連線不上伺服器
  2. 遠端 URL 不存在
  3. 無網路
  4. 出發了子類 HTTPError

簡要描述一下HTTPError 的狀態碼以及意義:

  • 200 (成功) 伺服器已成功處理了請求。 通常,這表示伺服器提供了請求的網頁。
  • 301 (永久移動) 請求的網頁已永久移動到新位置。 伺服器返回此響應(對 GET 或 HEAD 請求的響應)時,會自動將請求者轉到新位置。
  • 302 (臨時移動) 伺服器目前從不同位置的網頁響應請求,但請求者應繼續使用原有位置來進行以後的請求。
  • 304 (未修改) 自從上次請求後,請求的網頁未修改過。 伺服器返回此響應時,不會返回網頁內容。
  • 403 (禁止) 伺服器拒絕請求。
  • 404 (未找到) 伺服器找不到請求的網頁。
  • 500 (伺服器內部錯誤) 伺服器遇到錯誤,無法完成請求。
  • 501 (尚未實施) 伺服器不具備完成請求的功能。 例如,伺服器無法識別請求方法時可能會返回此程式碼。

    程式碼:

import urllib.request
import urllib.error

try:
    urllib.request.urlopen('https://www.google.com', timeout=1) #故意設定到某網站
except urllib.error.URLError as e:
    if hasattr(e, 'code'):
        print(e.code)
    if hasattr(e, 'reason'):
        print(e.reason)

'''
 if '測試' in 物件: 
 這種形式必須要可迭代的物件才能使用
     if 'reason' in e: # Wrong!
        print(e.reason)
'''

需要注意的是 HTTPError 是 URLError 的子類,而HTTPError 沒有 code 的方法,當然可以通過寫兩個 except: 解決,程式碼中的辦法也是可以的,然後 in 的使用必須用在可迭代的物件,不能隨便用 (:з」∠)