使用 Python 的 urllib.parse 庫解析 URL

來源:互聯網
上載者:User

使用 Python 的 urllib.parse 庫解析 URL

Python 中的 urllib.parse 模組提供了很多解析和組建 URL 的函數。

解析url
urlparse() 函數可以將 URL 解析成 ParseResult 對象。對象中包含了六個元素,分別為:

協議(scheme)
網域名稱(netloc)
路徑(path)
路徑參數(params)
查詢參數(query)
片段(fragment)
from urllib.parse import urlparse
url='http://user:pwd@domain:80/path;params?query=queryarg#fragment'
parsed_result=urlparse(url)
print('parsed_result 包含了',len(parsed_result),'個元素')
print(parsed_result)

結果為:

parsed_result 包含了6個元素
ParseResult(scheme='http', netloc='user:pwd@domain:80', path='/path', params='params', query='query=queryarg', fragment='fragment')
ParseResult 繼承於 namedtuple,因此可以同時通過索引和命名屬性來擷取 URL 中各部分的值。

為了方便起見, ParseResult 還提供了 username、 password、 hostname、 port 對 netloc 進一步進行拆分。

print('scheme :', parsed_result.scheme)
print('netloc :', parsed_result.netloc)
print('path :', parsed_result.path)
print('params :', parsed_result.params)
print('query :', parsed_result.query)
print('fragment:', parsed_result.fragment)
print('username:', parsed_result.username)
print('password:', parsed_result.password)
print('hostname:', parsed_result.hostname)
print('port :', parsed_result.port)

結果為:

scheme : http
netloc : user:pwd@domain:80
path :/path
params : params
query : query=queryarg
fragment: fragment
username: user
password:pwd
hostname: domain
port :80

除了 urlparse() 之外,還有一個類似的 urlsplit() 函數也能對 URL 進行拆分,所不同的是, urlsplit() 並不會把 路徑參數(params) 從 路徑(path) 中分離出來。

當 URL 中路徑部分包含多個參數時,使用 urlparse() 解析是有問題的:

url='http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg#fragment'
parsed_result=urlparse(url)
print(parsed_result)
print('parsed.path :', parsed_result.path)
print('parsed.params :', parsed_result.params)

結果為:

ParseResult(scheme='http', netloc='user:pwd@domain:80', path='/path1;params1/path2', params='params2', query='query=queryarg', fragment='fragment')
parsed.path :/path1;params1/path2
parsed.params : params2

這時可以使用 urlsplit() 來解析:

from urllib.parse import urlsplit
split_result=urlsplit(url)
print(split_result)
print('split.path :', split_result.path)
#SplitResult沒有 params 屬性

結果為:

SplitResult(scheme='http', netloc='user:pwd@domain:80', path='/path1;params1/path2;params2', query='query=queryarg', fragment='fragment')
split.path :/path1;params1/path2;params2

若只是要將 URL 後的 fragment 標識拆分出來,可以使用 urldefrag() 函數:

from urllib.parse import urldefrag
url ='http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg#fragment'
d = urldefrag(url)
print(d)
print('url :', d.url)
print('fragment:', d.fragment)

結果為:

DefragResult(url='http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg', fragment='fragment')
url : http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg
fragment: fragment

組建URL
ParsedResult 對象和 SplitResult 對象都有一個 geturl() 方法,可以返回一個完整的 URL 字串。

print(parsed_result.geturl())
print(split_result.geturl())

結果為:

http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg#fragment
http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg#fragment
但是 geturl() 只在 ParsedResult 和 SplitResult 對象中有,若想將一個普通的元組組成 URL,則需要使用 urlunparse() 函數:

from urllib.parse import urlunparse
url_compos =('http','user:pwd@domain:80','/path1;params1/path2','params2','query=queryarg','fragment')
print(urlunparse(url_compos))

結果為:

http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg#fragment

相對路徑轉換絕對路徑
除此之外,urllib.parse 還提供了一個 urljoin() 函數,來將相對路徑轉換成絕對路徑的 URL。

from urllib.parse import urljoin
print(urljoin('http://www.example.com/path/file.html','anotherfile.html'))
print(urljoin('http://www.example.com/path/','anotherfile.html'))
print(urljoin('http://www.example.com/path/file.html','../anotherfile.html'))
print(urljoin('http://www.example.com/path/file.html','/anotherfile.html'))

結果為:

http://www.example.com/path/anotherfile.html
http://www.example.com/path/anotherfile.html
http://www.example.com/anotherfile.html
http://www.example.com/anotherfile.html

查詢參數的構造和解析
使用 urlencode() 函數可以將一個 dict 轉換成合法的查詢參數:

from urllib.parse import urlencode
query_args ={
'name':'dark sun',
'country':'中國'
}
query_args = urlencode(query_args)
print(query_args)

結果為:

name=dark+sun&country=%E4%B8%AD%E5%9B%BD

可以看到特殊字元也被正確地轉義了。

相對的,可以使用 parse_qs() 來將查詢參數解析成 dict。

from urllib.parse import parse_qs
print(parse_qs(query_args))

結果為:

{'name':['dark sun'],'country':['中國']}
如果只是希望對特殊字元進行轉義,那麼可以使用 quote 或 quote_plus 函數,其中 quote_plus 比 quote 更激進一些,會把 :、/ 一類的符號也給轉義了。

from urllib.parse import quote, quote_plus, urlencode
url ='http://localhost:1080/~hello!/'
print('urlencode :', urlencode({'url': url}))
print('quote :', quote(url))
print('quote_plus:', quote_plus(url))

結果為:

urlencode : url=http%3A%2F%2Flocalhost%3A1080%2F%7Ehello%21%2F
quote : http%3A//localhost%3A1080/%7Ehello%21/
quote_plus: http%3A%2F%2Flocalhost%3A1080%2F%7Ehello%21%2F

可以看到 urlencode 中應該是調用 quote_plus 來進行轉義的。

逆向操作則使用 unquote 或 unquote_plus 函數:

from urllib.parse import unquote, unquote_plus
encoded_url ='http%3A%2F%2Flocalhost%3A1080%2F%7Ehello%21%2F'
print(unquote(encoded_url))
print(unquote_plus(encoded_url))

結果為:

http://localhost:1080/~hello!/
http://localhost:1080/~hello!/
你會發現 unquote 函數居然能正確地將 quote_plus 的結果轉換回來。

本文永久更新連結地址:https://www.bkjia.com/Linux/2018-02/151068.htm

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.