上一篇文章: Python3網絡爬蟲實戰---2一、使用Urllib:處理異常
下一篇文章: Python3網絡爬蟲實戰---2三、使用Urllib:分析Robots協議
Urllib 庫裏還提供了 parse 這個模塊,它定義了處理 URL 的標準接口,例如實現 URL 各部分的抽取,合併以及連接轉換。它支持以下協議的 URL 處理:file、ftp、gopher、hdl、http、https、imap、mailto、 mms、news、nntp、prospero、rsync、rtsp、rtspu、sftp、shttp、 sip、sips、snews、svn、svn+ssh、telnet、wais,本節咱們介紹一下該模塊中經常使用的方法來感覺一下它的便捷之處。php
urlparse() 方法能夠實現 URL 的識別和分段,咱們先用一個實例來感覺一下:html
from urllib.parse import urlparse result = urlparse('http://www.baidu.com/index.html;user?id=5#comment') print(type(result), result)
在這裏咱們利用了 urlparse() 方法進行了一個 URL 的解析,首先輸出瞭解析結果的類型,而後將結果也輸出出來。segmentfault
運行結果:網絡
<class 'urllib.parse.ParseResult'> ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')
觀察能夠看到,返回結果是一個 ParseResult 類型的對象,它包含了六個部分,分別是 scheme、netloc、path、params、query、fragment。數據結構
觀察一下實例的URL:ssh
http://www.baidu.com/index.html;user?id=5#comment
urlparse() 方法將其拆分紅了六部分,大致觀察能夠發現,解析時有特定的分隔符,好比 :// 前面的就是 scheme,表明協議,第一個 / 前面即是 netloc,即域名,分號 ; 前面是 params,表明參數。svn
因此能夠得出一個標準的連接格式以下:函數
scheme://netloc/path;parameters?query#fragment
一個標準的 URL 都會符合這個規則,利用 urlparse() 方法咱們能夠將它解析拆分開來。ui
除了這種最基本的解析方式,urlopen() 方法還有其餘配置嗎?接下來看一下它的 API 用法:編碼
urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
能夠看到它有三個參數:
咱們用一個實例感覺一下:
from urllib.parse import urlparse result = urlparse('www.baidu.com/index.html;user?id=5#comment', scheme='https') print(result)
運行結果:
ParseResult(scheme='https', netloc='', path='www.baidu.com/index.html', params='user', query='id=5', fragment='comment')
能夠發現,咱們提供的 URL 沒有包含最前面的 scheme 信息,可是經過指定默認的 scheme 參數,返回的結果是 https。
假設咱們帶上了 scheme 呢?
result = urlparse('http://www.baidu.com/index.html;user?id=5#comment', scheme='https')
結果以下:
ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')
可見 scheme 參數只有在 URL 中不包含 scheme 信息時纔會生效,若是 URL 中有 scheme 信息,那就返回解析出的 scheme。
下面咱們用一個實例感覺一下:
from urllib.parse import urlparse result = urlparse('http://www.baidu.com/index.html;user?id=5#comment', allow_fragments=False) print(result)
運行結果:
ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5#comment', fragment='')
假設 URL 中不包含 parameters 和 query 呢?
再來一個實例看下:
from urllib.parse import urlparse result = urlparse('http://www.baidu.com/index.html#comment', allow_fragments=False) print(result)
運行結果:
ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html#comment', params='', query='', fragment='')
能夠發現當 URL 中不包含 params 和 query 時, fragment 便會被解析爲 path 的一部分。
返回結果 ParseResult 其實是一個元組,咱們能夠用索引順序來獲取,也能夠用屬性名稱獲取,實例以下:
from urllib.parse import urlparse result = urlparse('http://www.baidu.com/index.html#comment', allow_fragments=False) print(result.scheme, result[0], result.netloc, result[1], sep='\n')
在這裏咱們分別用索引和屬性名獲取了 scheme 和 netloc,運行結果以下:
http http www.baidu.com www.baidu.com
能夠發現兩者結果是一致的,兩種方法均可以成功獲取。
有了 urlparse() 那相應地就有了它的對立方法 urlunparse()。
它接受的參數是一個可迭代對象,可是它的長度必須是 6,不然會拋出參數數量不足或者過多的問題。
先用一個實例感覺一下:
from urllib.parse import urlunparse data = ['http', 'www.baidu.com', 'index.html', 'user', 'a=6', 'comment'] print(urlunparse(data))
參數 data 用了列表類型,固然你也能夠用其餘的類型如元組或者特定的數據結構。
運行結果以下:
http://www.baidu.com/index.html;user?a=6#comment
這樣咱們就成功實現了 URL 的構造。
這個和 urlparse() 方法很是類似,只不過它不會單獨解析 parameters 這一部分,只返回五個結果。上面例子中的 parameters 會合併到 path中,用一個實例感覺一下:
from urllib.parse import urlsplit result = urlsplit('http://www.baidu.com/index.html;user?id=5#comment') print(result)
運行結果:
SplitResult(scheme='http', netloc='www.baidu.com', path='/index.html;user', query='id=5', fragment='comment')
能夠發現返回結果是 SplitResult,其實也是一個元組類型,能夠用屬性獲取值也能夠用索引來獲取,實例以下:
from urllib.parse import urlsplit result = urlsplit('http://www.baidu.com/index.html;user?id=5#comment') print(result.scheme, result[0])
運行結果:
http http
與 urlunparse() 相似,也是將連接的各個部分組合成完整連接的方法,傳入的也是一個可迭代對象,例如列表、元組等等,惟一的區別是,長度必須爲 5。
用一個實例來感覺一下:
from urllib.parse import urlunsplit data = ['http', 'www.baidu.com', 'index.html', 'a=6', 'comment'] print(urlunsplit(data))
運行結果:
http://www.baidu.com/index.html?a=6#comment
一樣能夠完成連接的拼接生成。
有了 urlunparse() 和 urlunsplit() 方法,咱們能夠完成連接的合併,不過前提必需要有特定長度的對象,連接的每一部分都要清晰分開。
生成連接還有另外一個方法,利用 urljoin() 方法咱們能夠提供一個 base_url(基礎連接),新的連接做爲第二個參數,方法會分析 base_url 的 scheme、netloc、path 這三個內容對新連接缺失的部分進行補充,做爲結果返回。
咱們用幾個實例來感覺一下:
from urllib.parse import urljoin print(urljoin('http://www.baidu.com', 'FAQ.html')) print(urljoin('http://www.baidu.com', 'https://cuiqingcai.com/FAQ.html')) print(urljoin('http://www.baidu.com/about.html', 'https://cuiqingcai.com/FAQ.html')) print(urljoin('http://www.baidu.com/about.html', 'https://cuiqingcai.com/FAQ.html?question=2')) print(urljoin('http://www.baidu.com?wd=abc', 'https://cuiqingcai.com/index.php')) print(urljoin('http://www.baidu.com', '?category=2#comment')) print(urljoin('www.baidu.com', '?category=2#comment')) print(urljoin('www.baidu.com#comment', '?category=2'))
運行結果:
http://www.baidu.com/FAQ.html https://cuiqingcai.com/FAQ.html https://cuiqingcai.com/FAQ.html https://cuiqingcai.com/FAQ.html?question=2 https://cuiqingcai.com/index.php http://www.baidu.com?category=2#comment www.baidu.com?category=2#comment www.baidu.com?category=2
能夠發現,base_url 提供了三項內容,scheme、netloc、path,若是這三項在新的連接裏面不存在,那麼就予以補充,若是新的連接存在,那麼就使用新的連接的部分。base_url 中的 parameters、query、fragments 是不起做用的。
經過如上的函數,咱們能夠輕鬆地實現連接的解析,拼合與生成。
咱們再介紹一個經常使用的 urlencode() 方法,它在構造 GET 請求參數的時候很是有用,咱們用實例感覺一下:
from urllib.parse import urlencode params = { 'name': 'germey', 'age': 22 } base_url = 'http://www.baidu.com?' url = base_url + urlencode(params) print(url)
咱們首先聲明瞭一個字典,將參數表示出來,而後調用 urlencode() 方法將其序列化爲 URL 標準 GET 請求參數。
運行結果:
http://www.baidu.com?name=germey&age=22
能夠看到參數就成功由字典類型轉化爲 GET 請求參數了。
這個方法很是經常使用,有時爲了更加方便地構造參數,咱們會事先用字典來表示,要轉化爲 URL 的參數時只須要調用該方法便可。
有了序列化必然就有反序列化,若是咱們有一串 GET 請求參數,咱們利用 parse_qs() 方法就能夠將它轉回字典,咱們用一個實例感覺一下:
from urllib.parse import parse_qs
query = 'name=germey&age=22'
print(parse_qs(query))
運行結果:
{'name': ['germey'], 'age': ['22']}
能夠看到這樣就成功轉回爲字典類型了。
另外還有一個 parse_qsl() 方法能夠將參數轉化爲元組組成的列表,實例以下:
from urllib.parse import parse_qsl query = 'name=germey&age=22' print(parse_qsl(query))
運行結果:
[('name', 'germey'), ('age', '22')]
能夠看到運行結果是一個列表,列表的每個元素都是一個元組,元組的第一個內容是參數名,第二個內容是參數值。
quote() 方法能夠將內容轉化爲 URL 編碼的格式,有時候 URL 中帶有中文參數的時候可能致使亂碼的問題,因此咱們能夠用這個方法將中文字符轉化爲 URL 編碼,實例以下:
from urllib.parse import quote keyword = '壁紙' url = 'https://www.baidu.com/s?wd=' + quote(keyword) print(url
在這裏咱們聲明瞭一箇中文的搜索文字,而後用 quote() 方法對其進行 URL 編碼,最後獲得的結果以下:
https://www.baidu.com/s?wd=%E...
這樣咱們就能夠成功實現URL編碼的轉換。
有了 quote() 方法固然還有 unquote() 方法,它能夠進行 URL 解碼,實例以下:
from urllib.parse import unquote url = 'https://www.baidu.com/s?wd=%E5%A3%81%E7%BA%B8' print(unquote(url))
這是上面獲得的 URL 編碼後的結果,咱們在這裏利用 unquote() 方法進行還原,結果以下:
https://www.baidu.com/s?wd=壁紙
能夠看到利用 unquote() 方法能夠方便地實現解碼。
本節介紹了 parse 模塊的一些經常使用 URL 處理方法,有了這些方法咱們能夠方便地實現 URL 的解析和構造,建議熟練掌握。
上一篇文章: Python3網絡爬蟲實戰---2一、使用Urllib:處理異常
下一篇文章: Python3網絡爬蟲實戰---2三、使用Urllib:分析Robots協議