爬蟲-urllib模塊的使用

urllib是Python中請求url鏈接的官方標準庫,在Python3中將Python2中的urllib和urllib2整合成了urllib。urllib中一共有四個模塊,分別以下:html

  • request:主要負責構造和發起網絡請求,定義了適用於在各類複雜狀況下打開 URL (主要爲 HTTP) 的函數和類
  • error:處理異常
  • parse:解析各類數據格式
  • robotparser:解析robot.txt文件

1、request模塊

1.urlopen()方法:

  • 在urlopen()方法中,直接寫入要訪問的url地址字符串,該方法就會主動的訪問目標網址,而後返回訪問結果,返回的訪問結果是一個http.client.HTTPResponse對象,該對象的常見方法有:
  1. read() :獲取訪問網頁獲取的數據,bytes類型
  2. info():返回響應頭信息
  3. getcode():返回Http狀態碼。
  4. geturl():返回請求的url
  • 發送簡單的GET請求

    from urllib.request import urlopen
    
    #向指定的url發送請求,並返回服務器響應的類文件對象
    resp = urlopen('https://www.baidu.com') 
    print(resp.read().decode())
  • 發送簡單的POST請求(data參數)

    from urllib.reuqest import urlopen
    from urllib.parse import urlencode
    
    #將字典類型的數據轉換成表單類型的數據格式,如"world=hello"
    data = urlencode({"word":"hello"}).encode()
    response = request.urlopen('http://httpbin.org/post', data=data)
    
    print(response.read().decode())

    默認的訪問方式是GET,當在urlopen()方法中傳入data參數時,則會發起POST請求。注意:傳遞的data數據須要爲bytes格式web

2.Request

  • 若是須要執行更復雜的操做,好比增長HTTP報頭,必須建立一個 Request 實例來做爲urlopen()的參數;而須要訪問的url地址則做爲 Request 實例的參數。
  • 爲了使爬蟲程序更像一個真實用戶,那咱們第一步就是須要假裝成一個被公認的瀏覽器,在發送請求的時候帶上User-Agent頭
    from urllib.request import Request,urlopen
    
    url = 'https://www.baidu.com/'
    ua_header = {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}
    #url連同headers一塊兒構造request請求,這個請求附帶IE 9.0瀏覽器的User-Agent
    request = Request(url,headers=ua_header)
    #向服務器發送請求
    resp = urlopen(request)
    print(resp.read().decode)

3.ProxyHandler處理器(代理IP)

  • 使用爬蟲來爬取數據的時候,若是過於頻繁的訪問,並且網站還設有限制的話,頗有可能會禁封咱們的ip地址,這個時候就須要設置代理,來隱藏咱們的真實IP。
  • 代理IP的原理:以本機先訪問代理IP,再經過代理IP地址訪問服務器,這樣服務器接受到的訪問IP就是代理IP地址。
    from urllib.request import build_opener,urlopen(),install_opener,Request,ProxyHandler
    
    # 構建了兩個代理Handler,一個有代理IP,一個沒有代理IP
    httpproxy_handler = urllib2.ProxyHandler({'http': '218.18.232.26:80', 'https': '218.18.232.26:80'})
    nullproxy_handler = urllib2.ProxyHandler({})
    
    proxySwitch = True #定義一個代理開關
    
    # 經過build_opener()方法使用這些代理Handler對象,建立自定義opener對象
    # 根據代理開關是否打開,使用不一樣的代理模式
    if proxySwitch:  
        opener = build_opener(httpproxy_handler)
    else:
        opener = build_opener(nullproxy_handler)
    
    request = Request("http://www.baidu.com/")
    
    # 1. 若是這麼寫,只有使用opener.open()方法發送請求才使用自定義的代理,而urlopen()則不使用自定義代理。
    resp = opener.open(request)
    
    # 2. 若是這麼寫,就是將opener應用到全局,以後全部的,不論是opener.open()仍是urlopen() 發送請求,都將使用自定義代理。
    # install_opener(opener)
    # resp = urlopen(request)
    
    print (resp.read().decode())

    若是代理須要受權驗證,簡單的方式是隻須要在ProxyHandler傳入的參數字典中,將值改成'用戶名:密碼@ip:端口號'這種形式,好比{"http":"myname:mypasswd@124.88.67.81:80"},複雜一點的須要建立一個密碼管理對象,下面會有介紹。瀏覽器

4.HTTPPasswordMgrWithDefaultRealm()

  • 利用這個類建立一個密碼管理對象,用來保存 HTTP 請求相關的用戶名和密碼,主要應用兩個場景:
  1. 驗證代理受權的用戶名和密碼 (ProxyBasicAuthHandler())
  2. 驗證Web客戶端的的用戶名和密碼 (HTTPBasicAuthHandler())

5.ProxyBasicAuthHandler(代理受權驗證)

  • 在使用私密代理時,須要經過受權驗證身份
    from urllib.request import HTTPPasswordMgrWithDefaultRealm,ProxyBasicAuthHandler,build_opener,Request
    
    # 私密代理受權的帳戶
    user = "mr_mao_hacker"
    # 私密代理受權的密碼
    passwd = "sffqry9r"
    # 私密代理 IP
    proxyserver = "61.158.163.130:16816"
    
    # 1. 構建一個密碼管理對象,用來保存須要處理的用戶名和密碼
    passwdmgr = HTTPPasswordMgrWithDefaultRealm()
    
    # 2. 添加帳戶信息,第一個參數realm是與遠程服務器相關的域信息,通常沒人管它都是寫None,後面三個參數分別是代理服務器、用戶名、密碼
    passwdmgr.add_password(None, proxyserver, user, passwd)
    
    # 3. 構建一個代理基礎用戶名/密碼驗證的ProxyBasicAuthHandler處理器對象,參數是建立的密碼管理對象
    #   注意,這裏再也不使用普通ProxyHandler類了
    proxyauth_handler = ProxyBasicAuthHandler(passwdmgr)
    
    # 4. 經過 build_opener()方法使用這些代理Handler對象,建立自定義opener對象,參數包括構建的 proxy_handler 和 proxyauth_handler
    opener = build_opener(proxyauth_handler)
    
    request = urllib2.Request("https://www.baidu.com/")
    resp = opener.open(request)
    print (resp.read().decode())

    注:一般用戶名和密碼不直接寫在程序中,而是存放在環境變量,或者單獨寫入一個模塊,而後從模塊導入服務器

6.HTTPBasicAuthHandler(WEB客戶端受權驗證)

  • 有些Web服務器(包括HTTP/FTP等)訪問時,須要進行用戶身份驗證,爬蟲直接訪問會報HTTP 401 錯誤,表示訪問身份未經受權
  • 若是咱們有客戶端的用戶名和密碼,只須要將上述代理受權驗證代碼中的ProxyBasicAuthHandler改爲HTTPBasicAuthHandler便可

7.Cookies

  • Cookies在爬蟲方面最典型的應用是斷定註冊用戶是否已經登陸網站,用戶可能會獲得提示,是否在下一次進入此網站時保留用戶信息以便簡化登陸手續。
  • 因爲urllib並無很好的處理cookie的對象,因此在這裏咱們須要用到一個別的庫,即http庫,並使用裏面的cookiejar來進行cookie的管理,該模塊主要的對象有主要的對象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar:
    • CookieJar:管理HTTP cookie值、存儲HTTP請求生成的cookie、向傳出的HTTP請求添加cookie的對象。整個cookie都存儲在內存中,對CookieJar實例進行垃圾回收後cookie也將丟失。cookie

    • FileCookieJar (filename,delayload=None,policy=None):從CookieJar派生而來,用來建立FileCookieJar實例,檢索cookie信息並將cookie存儲到文件中。filename是存儲cookie的文件名。delayload爲True時支持延遲訪問訪問文件,即只有在須要時纔讀取文件或在文件中存儲數據。網絡

    • MozillaCookieJar (filename,delayload=None,policy=None):從FileCookieJar派生而來,建立與Mozilla瀏覽器 cookies.txt兼容的FileCookieJar實例。ide

    • LWPCookieJar (filename,delayload=None,policy=None):從FileCookieJar派生而來,建立與libwww-perl標準的 Set-Cookie3 文件格式兼容的FileCookieJar實例。函數

  • 大多數狀況下,咱們只須要用到CookieJar(),若是須要和本地文件進行交互,就要用MozillaCookieJar()和LWPCookieJar(),下面就介紹幾種案例:
  1. 獲取cookie,並保存到CookieJar()中

    from http.cookiejar import CookieJar
    from urllib.request import Request,build_opener,HTTPCookieProcessor
    
    # 構建一個CookieJar對象實例來保存cookie
    cookiejar = cookielib.CookieJar()
    
    # 使用HTTPCookieProcessor()來建立cookie處理器對象,參數爲CookieJar()對象
    handler=HTTPCookieProcessor(cookiejar)
    
    opener = build_opener(handler)
    
    # 4. 以get方法訪問頁面,訪問以後會自動保存cookie到cookiejar中
    resp = opener.open("http://www.baidu.com")
    
    ## 能夠按標準格式將保存的Cookie打印出來
    cookieStr = ""
    for item in cookiejar:
        cookieStr = cookieStr + item.name + "=" + item.value + ";"
    
    ## 捨去最後一位的分號
    print cookieStr[:-1]
  2. 訪問網站得到cookie,並將cookie保存在本地文件中

    from http.cookiejar import MozillaCookieJar
    from urllib.request import Request,build_opener,HTTPCookieProcessor
    
    # 保存cookie的本地磁盤文件名
    filename = 'cookie.txt'
    
    #聲明一個MozillaCookieJar(有save實現)對象實例來保存cookie,以後寫入文件
    cookiejar = MozillaCookieJar(filename)
    
    # 使用HTTPCookieProcessor()來建立cookie處理器對象,參數爲CookieJar()對象
    handler = HTTPCookieProcessor(cookiejar)
    
    opener = build_opener(handler)
    response = opener.open("https://www.baidu.com/")
    
    # 保存cookie到本地文件
    cookiejar.save()
  3. 從文件中獲取cookie

    from http.cookiejar import MozillaCookieJar
    from urllib.request import Request,build_opener,HTTPCookieProcessor
    
    #建立MozillaCookieJar(有load實現)實例對象
    cookiejar = MozillaCookieJar(filename)
    
    #從文件中讀取cookie內容到對象
    cookiejar.load('cookie.txt')
    
    # 使用HTTPCookieProcessor()來建立cookie處理器對象,參數爲CookieJar()對象
    handler = HTTPCookieProcessor(cookiejar)
    
    opener = build_opener(handler)
    response = opener.open("https://www.baidu.com/")

8.處理HTTPS請求SSL證書驗證

  • 最簡單的方法就是經過添加忽略ssl證書驗證關閉證書驗證,因爲urllib並無很好的處理ssl的對象,因此在這裏咱們須要用到一個別的庫,即ssl庫,以下:
    import ssl
    from urllib.request import urlopen,Request
    
    # 表示忽略未經覈實的SSL證書認證
    context = ssl._create_unverified_context()
    
    url = "https://www.12306.cn/mormhweb/"
    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"}
    request = Request(url,headers=headers)
    
    # 在urlopen()方法裏 指明添加 context 參數
    resp = urlopen(request, context=context)
    print(resp.read().decode())

2、error模塊

  • 在urllib中主要設置了兩個異常,一個是URLError,一個是HTTPError,HTTPError是URLError的子類。

1.URLError

  • URLError產生的緣由主要有:
  1. 沒有網絡鏈接
  2. 服務器鏈接失敗
  3. 找不到指定的服務器
  • 下面訪問一個不存在的域名:
    from urllib.error import URLError
    from urllib.request import Request,urlopen
    
    request = Request('http://www.fafafasfdaffaf.com/')
    try:
        resp = urlopen(request)
    except URLError as e:
        print(e)

2.HTTPError

  • HTTPError包含了三個屬性:
  1. code:請求的狀態碼
  2. reason:錯誤的緣由
  3. headers:響應的報頭
    from urllib.error import HTTPError
    from urllib.request import Request,urlopen
    
    requset = Request('http://www.baidu.com/lfafdaflafapae.html')
    
    try:
        resp = urlopen(requset)
    except HTTPError as e:
        print(e)
        print(e.code)
        print(e.reason)
        print(e.headers)

3、parse模塊

data參數須要用urllib.parse模塊對其進行數據格式處理。post

  • urllib.parse.quote(url):(URL編碼處理)主要對URL中的非ASCII碼編碼處理
  • urllib.parse.unquote(url):(URL解碼處理)URL上的特殊字符還原
  • urllib.parse.urlencode(data):對請求數據data進行格式轉換
相關文章
相關標籤/搜索