前面說過,urllib庫裏還提供了parse
這個模塊,它定義了處理URL的標準接口,例如實現URL各部分的抽取、合併以及連接轉換。它支持以下協議的URL處理:file、ftp、gopher、hdl、http、https、imap、mailto、 mms、news、nntp、prospero、rsync、rtsp、rtspu、sftp、 sip、sips、snews、svn、svn+ssh、telnet和wais。本節中,咱們介紹一下該模塊中經常使用的方法來看一下它的便捷之處。php
該方法能夠實現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的解析。首先,輸出瞭解析結果的類型,而後將結果也輸出出來。bash
運行結果以下:微信
<class 'urllib.parse.ParseResult'>
ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')
複製代碼
能夠看到,返回結果是一個ParseResult
類型的對象,它包含6部分,分別是scheme
、netloc
、path
、params
、query
和fragment
。網絡
觀察一下該實例的URL:數據結構
http://www.baidu.com/index.html;user?id=5#comment
複製代碼
能夠發現,urlparse()
方法將其拆分紅了6部分。大致觀察能夠發現,解析時有特定的分隔符。好比,://前面的就是scheme
,表明協議;第一個/前面即是netloc
,即域名;分號;前面是params
,表明參數。ssh
因此,能夠得出一個標準的連接格式,具體以下:svn
scheme://netloc/path;parameters?query#fragment
複製代碼
一個標準的URL都會符合這個規則,利用urlparse()
方法能夠將它拆分開來。ui
除了這種最基本的解析方式外,urlopen()
方法還有其餘配置嗎?接下來,看一下它的API用法:編碼
urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
複製代碼
能夠看到,它有3個參數。
urlstring
:這是必填項,即待解析的URL。scheme
:它是默認的協議(好比http
或https
等)。假如這個連接沒有帶協議信息,會將這個做爲默認的協議。咱們用實例來看一下: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
。
allow_fragments
:便是否忽略fragment
。若是它被設置爲False
,fragment
部分就會被忽略,它會被解析爲path
、parameters
或者query
的一部分,而fragment
部分爲空。下面咱們用實例來看一下: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中不包含params
和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()
方法很是類似,只不過它再也不單獨解析params
這一部分,只返回5個結果。上面例子中的params
會合併到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
這3個內容並對新連接缺失的部分進行補充,最後返回結果。
下面經過幾個實例看一下:
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
。若是這3項在新的連接裏不存在,就予以補充;若是新的連接存在,就使用新的連接的部分。而base_url
中的params
、query
和fragment
是不起做用的。
經過urljoin()
方法,咱們能夠輕鬆實現連接的解析、拼合與生成。
這裏咱們再介紹一個經常使用的方法——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()
方法將其序列化爲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')]
複製代碼
能夠看到,運行結果是一個列表,而列表中的每個元素都是一個元組,元組的第一個內容是參數名,第二個內容是參數值。
該方法能夠將內容轉化爲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=%E5%A3%81%E7%BA%B8
複製代碼
有了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網絡爬蟲開發實戰教程 | 靜覓
如想了解更多爬蟲資訊,請關注個人我的微信公衆號:進擊的Coder
weixin.qq.com/r/5zsjOyvEZ… (二維碼自動識別)