爬蟲系列(三) urllib的基本使用

1、urllib 簡介

urllib 是 Python3 中自帶的 HTTP 請求庫,無需複雜的安裝過程便可正常使用,十分適合爬蟲入門html

urllib 中包含四個模塊,分別是python

  • request:請求處理模塊
  • parse:URL 處理模塊
  • error:異常處理模塊
  • robotparser:robots.txt 解析模塊

如下咱們將會分別講解 urllib 中各模塊的使用方法,可是因爲篇幅問題,本文只會涉及模塊中比較經常使用的內容json

詳細內容能夠參考官方文檔:https://docs.python.org/3.7/library/urllib.html瀏覽器

2、urllib 使用

在開始講解前,先給你們提供一個用於測試的網站,http://www.httpbin.org/cookie

這個網站能夠在頁面上返回所發送 請求 的相關信息,十分適合練習使用網絡

好了,下面正式開始!session

一、request 模塊

request 模塊是 urllib 中最重要的一個模塊,通常用於 發送請求和接收響應app

(1)urlopen 方法

urllib.request.urlopen()

urlopen 方法無疑是 request 模塊中最經常使用的方法之一,常見的參數說明以下:dom

  • url:必填,字符串,指定目標網站的 URLsocket

  • data:指定表單數據

    該參數默認爲 None,此時 urllib 使用 GET 方法 發送請求

    當給參數賦值後,urllib 使用 POST 方法 發送請求,並在該參數中攜帶表單信息(bytes 類型)

  • timeout:可選參數,用來指定等待時間,若超過指定時間還沒得到響應,則拋出一個異常

該方法始終返回一個 HTTPResponse 對象,HTTPResponse 對象常見的屬性和方法以下:

  • geturl():返回 URL
  • getcode():返回狀態碼
  • getheaders():返回所有響應頭信息
  • getheader(header):返回指定響應頭信息
  • read():返回響應體(bytes 類型),一般須要使用 decode('utf-8') 將其轉化爲 str 類型

例子1:發送 GET 請求

>>> import urllib.request
>>> url = 'http://www.httpbin.org/get'
>>> response = urllib.request.urlopen(url)
>>> type(response)
# <class 'http.client.HTTPResponse'>
>>> response.geturl()
# 'http://www.httpbin.org/get'
>>> response.getcode()
# 200
>>> response.getheaders()
# [('Connection', 'close'), ('Server', 'gunicorn/19.9.0'), ('Date', 'Sat, 11 Aug 2018 01:39:14 GMT'), ('Content-Type', 'application/json'), ('Content-Length', '243'), ('Access-Control-Allow-Origin', '*'), ('Access-Control-Allow-Credentials', 'true'), ('Via', '1.1 vegur')]
>>> response.getheader('Connection')    
# 'close'
>>> print(response.read().decode('utf-8'))
# {
#   "args": {}, 
#   "headers": {
#     "Accept-Encoding": "identity", 
#     "Host": "www.httpbin.org", 
#     "User-Agent": "Python-urllib/3.7"
#   }, 
#   "origin": "183.6.159.80, 183.6.159.80", 
#   "url": "https://www.httpbin.org/get"
# }

例子2:發送 POST 請求

urllib.parse.urlencode():進行 URL 編碼,其實是將 dict 類型數據轉化成 str 類型數據

encode('utf-8'):將 str 類型數據轉化成 bytes 類型數據

>>> import urllib.request
>>> import urllib.parse
>>> url = 'http://www.httpbin.org/post'
>>> params = {
    'from':'AUTO',
    'to':'AUTO'
}
>>> data = urllib.parse.urlencode(params).encode('utf-8')
>>> response = urllib.request.urlopen(url=url,data=data)
>>> html =  response.read().decode('utf-8')
>>> print(html)
# {
#   "args": {}, 
#   "data": "", 
#   "files": {}, 
#   "form": { # 這是咱們設置的表單數據
#     "from": "AUTO", 
#     "to": "AUTO"
#   }, 
#   "headers": {
#     "Accept-Encoding": "identity", 
#     "Connection": "close", 
#     "Content-Length": "17", 
#     "Content-Type": "application/x-www-form-urlencoded", 
#     "Host": "www.httpbin.org", 
#     "User-Agent": "Python-urllib/3.6"
#   }, 
#   "json": null, 
#   "origin": "116.16.107.180", 
#   "url": "http://www.httpbin.org/post"
# }

(2)Request 對象

實際上,咱們還能夠給 urllib.request.open() 方法傳入一個 Request 對象做爲參數

爲何還須要使用 Request 對象呢?由於在上面的參數中咱們沒法指定 請求頭部,而它對於爬蟲而言又十分重要

不少網站可能會首先檢查請求頭部中的 USER-AGENT 字段來判斷該請求是否由網絡爬蟲程序發起

可是經過修改請求頭部中的 USER_AGENT 字段,咱們能夠將爬蟲程序假裝成瀏覽器,輕鬆繞過這一層檢查

這裏提供一個查找經常使用的 USER-AGENT 的網站:

urllib.request.Request()

參數說明以下:

  • url:指定目標網站的 URL
  • data:發送 POST 請求時提交的表單數據,默認爲 None
  • headers:發送請求時附加的請求頭部,默認爲 {}
  • origin_req_host:請求方的 host 名稱或者 IP 地址,默認爲 None
  • unverifiable:請求方的請求沒法驗證,默認爲 False
  • method:指定請求方法,默認爲 None
>>> import urllib.request
>>> url = 'http://www.httpbin.org/headers'
>>> headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
>>> req = urllib.request.Request(url, headers=headers, method='GET')
>>> response = urllib.request.urlopen(req)
>>> html = response.read().decode('utf-8')
>>> print(html)
# {
#   "headers": {
#     "Accept-Encoding": "identity", 
#     "Connection": "close", 
#     "Host": "www.httpbin.org", 
#     "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 這是咱們設置的 User-Agent
#   }
# }

什麼是 Cookie?

Cookie 是指某些網站爲了辨別用戶身份、進行 session 跟蹤而儲存在用戶本地終端上的數據

① 獲取 Cookie

>>> import urllib.request
>>> import http.cookiejar
>>> cookie = http.cookiejar.CookieJar()
>>> cookie_handler = urllib.request.HTTPCookieProcessor(cookie)
>>> opener = urllib.request.build_opener(cookie_handler)
>>> response = opener.open('http://www.baidu.com')
>>> for item in cookie:
        print(item.name + '=' + item.value)
        
        
# BAIDUID=486AED46E7F22C0A7A16D9FE6E627846:FG=1
# BDRCVFR[RbWYmTxDkZm]=mk3SLVN4HKm
# BIDUPSID=486AED46E7F22C0A7A16D9FE6E627846
# H_PS_PSSID=1464_21106_26920
# PSTM=1533990197
# BDSVRTM=0
# BD_HOME=0
# delPer=0

② 使用 Cookie

>>> import urllib.request
>>> import http.cookiejar
>>> # 將 Cookie 保存到文件
>>> cookie = http.cookiejar.MozillaCookieJar('cookie.txt')
>>> cookie_handler = urllib.request.HTTPCookieProcessor(cookie)
>>> opener = urllib.request.build_opener(cookie_handler)
>>> response = opener.open('http://www.baidu.com')
>>> cookie.save(ignore_discard=True,ignore_expires=True)
>>> # 從文件讀取 Cookie 並添加到請求中
>>> cookie = http.cookiejar.MozillaCookieJar()
>>> cookie = cookie.load('cookie.txt',ignore_discard=True,ignore_expires=True)
>>> cookie_handler = urllib.request.HTTPCookieProcessor(cookie)
>>> opener = urllib.request.build_opener(cookie_handler)
>>> response = opener.open('http://www.baidu.com')
>>> # 此時已經獲得帶有 Cookie 請求返回的響應

(4)使用代理

對於某些網站,若是同一個 IP 短期內發送大量請求,則可能會將該 IP 斷定爲爬蟲,進而對該 IP 進行封禁

因此咱們有必要使用隨機的 IP 地址來繞開這一層檢查,這裏提供幾個查找免費的 IP 地址的網站:

注意,免費的代理 IP 基本上十分不穩定,並且還可能隨時更新,因此最好本身寫一個爬蟲去維護

>>> import urllib.request
>>> import random
>>> ip_list = [
    {'http':'61.135.217.7:80'},
    {'http':'182.88.161.204:8123'}
]
>>> proxy_handler = urllib.request.ProxyHandler(random.choice(ip_list))
>>> opener = urllib.request.build_opener(proxy_handler)
>>> response = opener.open('http://www.httpbin.org/ip')
>>> print(response.read().decode('utf-8'))
# {
#   "origin": "61.135.217.7"
# }

二、parse 模塊

parse 模塊通常能夠用於處理 URL

(1)quote 方法

當你在 URL 中使用中文時,你會發現程序會出現莫名其妙的錯誤

>>> import urllib.request
>>> url = 'https://www.baidu.com/s?wd=爬蟲'
>>> response = urllib.request.urlopen(url)
# UnicodeEncodeError: 'ascii' codec can't encode characters in position 10-11: ordinal not in range(128)

這時,quote 方法就能夠派上用場了,它使用轉義字符替換特殊字符,從而將上面的 URL 處理成合法的 URL

>>> import urllib.parse
>>> url = 'https://www.baidu.com/s?wd=' + urllib.parse.quote('爬蟲')
>>> url
# 'https://www.baidu.com/s?wd=%E7%88%AC%E8%99%AB'

(2)urlencode 方法

urlencode 方法在上面的文章中曾經用到過,不知道你們還有沒有印象,這裏咱們再從新回顧一遍

簡單來講,urlencode 方法就是將 dict 類型數據轉化爲符合 URL 標準的 str 類型數據,請看演示:

>>> import urllib.parse
>>> params = {
    'from':'AUTO',
    'to':'AUTO'
}
>>> data = urllib.parse.urlencode(params)
>>> data
# 'from=AUTO&to=AUTO'

(3)urlparse 方法

urlparse 方法用於解析 URL,返回一個 ParseResult 對象

該對象能夠認爲是一個六元組,對應 URL 的通常結構:scheme://netloc/path;parameters?query#fragment

>>> import urllib.parse
>>> url = 'http://www.example.com:80/python.html?page=1&kw=urllib'
>>> url_after = urllib.parse.urlparse(url)
>>> url_after
# ParseResult(scheme='http', netloc='www.example.com:80', path='/python.html', params='', query='page=1', fragment='urllib')
>>> url_after.port
# 80

三、error 模塊

error 模塊通常用於進行異常處理,其中包含兩個重要的類:URLErrorHTTPError

注意,HTTPError 是 URLError 的子類,因此捕獲異常時通常要先處理 HTTPError,經常使用的格式以下:

>>> import urllib.request
>>> import urllib.error
>>> import socket
>>> try:
    response = urllib.request.urlopen('http://www.httpbin.org/get', timeout=0.1)
except urllib.error.HTTPError as e:
    print("Error Code: ", e.code)
    print("Error Reason: ", e.reason)
except urllib.error.URLError as e:
    if isinstance(e.reason, socket.timeout):
        print('Time out')
else:
    print('Request Successfully')
    
# Time out

【參考資料】

【爬蟲系列相關文章】

相關文章
相關標籤/搜索