【譯】urllib.parse文檔--這裏有關於URL的一切

本模塊定義了一個標準接口,既可以把統一資源定位符(URL)解析爲若干部分(通信協議,網絡地址和路徑等),也可以把各個部分重新組合成URL,還可以利用“基本URL”把相對路徑轉化爲絕對路徑。

本模塊設計之初就考慮到要兼容一系列和URL相關的RFC標準。目前能夠支持的URL協議包括:file, ftp, gopher, hdl,http, https, imap, mailto, mms, nntp, prospero, rsync, rtsp, rtspu, sftp, shttp, sip, sips, snews, svn, svn+ssh, telnet, wais, ws, wss

urllib.parse定義的函數主要分爲兩類:URL解析和URL轉義。下面詳細介紹一下本模塊的細節。

1.URL 解析

URL解析函數聚焦於將URL分割爲若干部分,以及將各個部分拼接爲URL。

 

urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)

    本函數將URL解析爲6個部分,返回一個包含6個元素的named tuple。這麼處理符合URL的通用結構:

scheme://netloc/path;parameters?query#fragment

    每個元組的元素都是一個字符串(也有可能爲空字符串)。這些結構並不會再進行更細緻的劃分(例如網絡地址整個作爲一個字符串),並且不會還原%的轉義。除了path開頭的斜槓,各個部分之間的分割符號並不會在解析結果中出現。舉例來說:

>>> from urllib.parse import urlparse>>> o = urlparse('http://www.cwi.nl:80/%7Eguido/Python.html')>>> oParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',            params='', query='', fragment='')>>> o.scheme'http'>>> o.port80>>> o.geturl()'http://www.cwi.nl:80/%7Eguido/Python.html'根據 RFC1808 定義的語法規則,urlparse模塊僅能識別以‘//’開頭的網絡地址。其他的輸入均會被當作相對URL從而解析爲路徑部分。
>>> from urllib.parse import urlparse>>> urlparse('//www.cwi.nl:80/%7Eguido/Python.html')ParseResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',            params='', query='', fragment='')>>> urlparse('www.cwi.nl/%7Eguido/Python.html')ParseResult(scheme='', netloc='', path='www.cwi.nl/%7Eguido/Python.html',            params='', query='', fragment='')>>> urlparse('help/Python.html')ParseResult(scheme='', netloc='', path='help/Python.html', params='',            query='', fragment='')

通過 scheme 參數傳入的地址協議僅會在URL不包含網絡協議的時候纔會用到。除了缺省的空字符(特殊情況下可以自動轉化爲b'')之外,該入參應該同urlstring保持類型一致(文本或者字節)。

如果 allow_fragments 入參爲false,返回結果中的fragment部分將不會有具體值,而是僅返回一個空字符串。URL中的該部分會被解析爲path或者query的一部分。

以named tuple形式出現的返回值,既可以通過索引讀取,也可以通過別名讀取。

屬性

索引

值(如果不存在)

scheme

0

URL方案說明符

scheme parameter

netloc

1

網絡位置部分

空字符串

path

2

分層路徑

空字符串

params

3

最後路徑元素的參數

空字符串

query

4

查詢組件

空字符串

fragment

5

片段識別

空字符串

username

 

用戶名

None

password

 

密碼

None

hostname

 

主機名(小寫)

None

port

 

端口號爲整數(如果存在)

None

 

如果URL中出現了非法的端口地址,在讀取獲取解析結果中的port值時會拋出ValueError。稍後會有更多詳細的說明。

如果netloc部分的方括號不匹配也會拋出ValueError。

如果netloc在NFKC規範(使用IDNA編碼)中包含/, ?, #, @或者:,將會拋出ValueError異常。但是如果顯式的這樣傳入這種值來拼裝URL,不需要解析的情況下,不會拋異常。

作爲named tuple的子類,解析結果中的某些特有方法和屬性可能有特殊用途。舉個例子,_replace()將會返回另一個替換指定部分之後的解析結果。

>>> from urllib.parse import urlparse
>>> u = urlparse('//www.cwi.nl:80/%7Eguido/Python.html')
>>> u
ParseResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',
            params='', query='', fragment='')
>>> u._replace(scheme='http')
ParseResult(scheme='http',    netloc='www.cwi.nl:80', path='/%7Eguido/ Python.html',
            params='', query='', fragment='')

 

urllib.parse.parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None)

該函數用於解析application/x-www-form-urlencoded類型的query字符串。返回值爲字典類型,其中字典的key是唯一的,字典的value是list類型。

keep_blank_values 用於決定通過%轉義的空格是否當作空字符串處理。當入參值爲true的時候,保留作爲空字符串。缺省值爲false,此時空格會被忽略,當作不存在。

strict_parsing用於決定如何處理解析錯誤。缺省狀態下爲false,此時將會忽略異常。如果置爲true,遇到錯誤會拋出ValueError異常。

encoding和errors的含義和bytes.decode()類似,用於決定如何將含有%的轉義字符解析爲Unicode字符。

max_num_fields用於決定最多可以讀取多少字段。設置之後,如果發現多於設置的值,將會拋出ValueError異常。

使用urllib.parse.urlencode()函數(入參doseq設置爲True)可以將結果再次轉換爲query字符串。

 

urllib.parse.parse_qsl(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None)

該函數用於解析application/x-www-form-urlencoded類型的字符串數據。返回值爲name,value組合的list(同parse_qs的區別在於返回值類型)。

keep_blank_values 用於決定通過%轉義的空格是否當作空字符串處理。當入參值爲true的時候,保留作爲空字符串。缺省值爲false,此時空格會被忽略,當作不存在。

strict_parsing用於決定如何處理解析錯誤。缺省狀態下爲false,此時將會忽略異常。如果置爲true,遇到錯誤會拋出ValueError異常。

encoding和errors的含義和bytes.decode()類似,用於決定如何將含有%的轉義字符解析爲Unicode字符。

max_num_fields用於決定最多可以讀取多少字段。設置之後,如果發現多於設置的值,將會拋出ValueError異常。

使用urllib.parse.urlencode()函數可以將結果再次轉換爲query字符串。

urllib.parse.urlunparse(parts)

將urlparse()返回的tuple重新組合成一個URL。parts參數接受任何包含6個元素的可迭代對象。返回結果同原始URL相比可能會有細微差別,但是保證含義是一致的,尤其是在原始URL包含非必需的分隔符時(舉例來說,RFC明確指出“?”是有效的query字符串)。

urllib.parse.urlsplit(urlstring, scheme='', allow_fragments=True)

和urlparse()有些類似,區別在於本函數不會分割URL中的params部分。如果你覺得params是path的一部分(參考RFC 2396),此時應該使用本函數,而不是urlparse()。本函數的設計初衷爲了能夠單獨處理path和params。函數的返回值爲包含5個元素的named tuple:

(addressing scheme, network location, path, query, fragment identifier)

返回值是named tuple類型,既可以通過索引讀取,也可以通過別名讀取:

別名 索引 缺省值
scheme 0 URL的網絡協議 協議規範
netloc 1 網絡地址 空字符串
path 2 地址路徑 空字符串
query 3 查詢參數 空字符串
fragment 4 片段參數 空字符串
username 5 用戶名 None
password   密碼 None
hostname   主機地址(小寫) None
port   存在的情況下爲整數端口 None

如果URL中出現了非法的端口地址,在讀取獲取解析結果中的port值時會拋出ValueError。更多的說明可以翻閱**解析結果的構成**。

如果netloc部分的方括號不匹配也會拋出ValueError。

如果netloc在NFKC規範(使用IDNA編碼)中包含/, ?, #, @或者:,將會拋出ValueError異常。但是如果顯式的這樣傳入URL的各個部分,不需要解析的情況下,不會拋異常。    如果netloc部分的方括號不匹配也會拋出ValueError。    如果URL中出現了非法的端口地址,在讀取獲取解析結果中的port值時會拋出ValueError。更多的說明可以翻閱解析結果的構成。

urllib.parse.urlunsplit(parts)

將urlsplite()返回的tuple重新組合成一個URL。parts參數接受任何包含5個元素的可迭代對象。返回結果同原始URL相比可能會有細微差別,但是保證含義是一致的,尤其是在原始URL包含非必需的分隔符時(舉例來說,RFC明確說明“?”是有效的query字符串)。

urllib.parse.urljoin(base, url, allow_fragments=True)

將基地址和url組合成一個絕對URL。需要注意的是,本函數會使用scheme, netloc以及(部分的)path,來補全相對URL中缺失的部分。舉個例子:

>>> from urllib.parse import urljoin>>> urljoin('http://www.cwi.nl/%7Eguido/Python.html', 'FAQ.html')'http://www.cwi.nl/%7Eguido/FAQ.html

入參allow_fragments的含義同urlparse()一致。

注意:即使url是一個絕對URL(以//或者scheme://開頭),url中的host以及scheme也會被替換。舉個例子:

>>> urljoin('http://www.cwi.nl/%7Eguido/Python.html',            '//www.python.org/%7Eguido')'http://www.python.org/%7Eguido'

如果你不希望這樣處理,可以使用urlsplit()以及urlunsplit()預先處理url,去掉scheme和netloc部分。

urllib.parse.urldefrag(url)

如果url中包含fragment,本函數將會返回一個不帶有fragment的url,以及截取的fragment。如果url中不包含fragment,本函數將返回原始url和一個空字符串。

返回值是一個named tuple類型,既可以通過索引讀取,也可以通過別名讀取:

別名 索引 缺省值
url 0 不含fragment的url 空字符串
fragment 1 片段參數 空字符串

更多的說明可以翻閱解析結果的構成。

 

urllib.parse.unwrap(url)

本函數用於從一個被包裹的URL(形如<URL:scheme://host/path>,<scheme://host/path>, URL:scheme://host/path or scheme://host/path)中摘取出實際URL。如果url沒有被包裹,則返回原始值。

解析ASCII編碼

URL解析函數設計之初是僅僅是爲了處理字符類型。在實踐中,往往需要處理ASCII編碼和轉義的URL。因此,本模塊的URL解析函數都可以處理bytes,bytearray以及str類型的對象。

如果入參是str類型,返回值也會是str。如果入參是bytes或者bytearray,結果就會只有bytes數據。

如果試圖在一個函數裏面混合使用字符串和字節類型會拋出TypeError異常,如果試圖使用不是ASCII類型的字節會拋出UnicodeDecodeError異常。

爲了方便的將結果在字符串和字節之間轉換,所有的URL解析函數的返回值要麼帶有encode()方法(字符串類型的返回值),要麼帶有decode() 方法(字節類型的返回值)。這些函數的使用方式和str(), bytes() 一樣(唯一的細微區別在於默認的編碼形式是‘ascii’,而不是‘utf-8’)。encode() 方法返回bytes類型,decode() 方法返回str類型。

如果調用方期望處理沒有正確轉義的URL(可能含有非ASCII字符),需要在調用URL解析函數之前自己將字節類型轉化爲字符。

上述文檔介紹的細節僅適用於URL解析函數。URL轉義函數在處理字節時有自己的一套規則,感興趣的可以參考URL轉義函數的文檔。

解析結果的數據結構

urlparse(), urlsplit() 以及urldefrag() 函數的返回對象都是tuple的子類。這些子類獨有的一些特性在介紹函數的時候提到過了,例如上一部分剛剛介紹過的編碼和解碼都是作爲附加的方法出現的,另外還有解析結構還有一些方法如下:

urllib.parse.SplitResult.geturl()

該方法返回重新組合的url字符串,它和原始url的區別在於,它會將scheme轉爲小寫,並去掉原來爲空的一些部分:空parameter、空query以及空fragment。

對於urldefrag()函數而言,只會去掉空的fragment。對於urlsplit()和urlparse(),上面提到的差別都會生效。

多次將本函數的返回值傳入解析函數,得到的結果將不會有任何變化。

>>> from urllib.parse import urlsplit>>> url = 'HTTP://www.Python.org/doc/#'>>> r1 = 1urlsplit(url)>>> r1.geturl()'http://www.Python.org/doc/'>>> r2 = urlsplit(r1.geturl())>>> r2.geturl()'http://www.Python.org/doc/'

以str類型的處理爲例,下面介紹幾個解析結構的具體實現:

class urllib.parse.DefragResult(url, fragment)

urldefrag()返回結果的具體實現,結果包含str類型的數據。其encode()方法會返回一個DefrageResultBytes實例。

class urllib.parse.ParseResult(scheme, netloc, path, params, query, fragment)

urlparse()返回結果的具體實現,結果包含str類型的數據。其encode()方法會返回一個 ParseResultBytes 實例。

class urllib.parse.SplitResult(scheme, netloc, path, query, fragment)

urlsplit()返回結果的具體實現,結果包含str類型的數據。其encode()方法會返回一個 SplitResultBytes實例。

以bytes類型的處理爲例,下面介紹幾個解析結構的具體實現:

class urllib.parse.DefragResultBytes(url, fragment)

urldefrag()返回結果的具體實現,結果包含str類型的數據。其decode()方法會返回一個DefragResult實例。

class urllib.parse.ParseResultBytes(scheme, netloc, path, params, query, fragment)

urlparse()返回結果的具體實現,結果包含str類型的數據。其decode()方法會返回一個ParseResult實例。

class urllib.parse.SplitResultBytes(scheme, netloc, path, query, fragment)

urlsplit()返回結果的具體實現,結果包含str類型的數據。其decode()方法會返回一個 SplitResult實例。

2.URL轉義

URL轉義函數是爲了使得編程數據能夠安全的使用,主要分爲轉義特殊字符和編碼非ASCII字符兩個部分,另外還有對應的逆向操作。

 

urllib.parse.quote(string, safe='/', encoding=None, errors=None)

以%xx的形式轉義特殊字符,但是字母、數字以及 _ . - ~ 這幾個字符是不會被轉義的。默認情況下,該函數是爲了轉義URL中的path部分。當然,可以通過safe參數,明確指定哪些ASCII字符不希望被轉義,其缺省值爲"/"。

string入參既可以是str類型,也可以是bytes類型。

encoding和errors的含義和str.encode()類似,用於決定如何處理非ASCII字符。encoding缺省值爲‘utf-8’。errors缺省值爲‘strict’,即嚴格模式——如果遇到不支持的字符將會拋出UnicodeEncodeError異常。如果string入參爲bytes類型,那麼encoding和errors入參將不能夠支持自定義,否則會拋出TypeError異常。

需要指出的是,quote(string, safe, encoding, errors)和quotefrombytes(string.encode(encoding, errors), safe)含義是一致的。

示例:quote('/El Niño/')會返回'/El%20Ni%C3%B1o/'。

urllib.parse.quote_plus(string, safe='', encoding=None, errors=None)

本函數和quote()類似,區別在於會用加號來轉義空格,這麼做主要是因爲通常需要將query部分附加到URL上的時候需要轉義HTML數據。除非通過safe參數明確指出加號不需要轉義,否則該函數會自動轉義加號。另外,safe入參的缺省值去掉了‘/’。

示例:quote_plus('/El Niño/') 會返回 '%2FEl+Ni%C3%B1o%2F'

urllib.parse.quote_from_byte(bytes, safe='/')

本函數和quote()類似,但是僅接受bytes類型的入參,不接受str類型,並且不支持string到bytes的轉碼。

示例:quotefrombytes(b'a&\xef') 會返回 'a%26%EF'

urllib.parse.unquote(string, encoding='utf-8', errors='replace')

本函數可以將%xx形式的轉義字符還原爲單個字符。encoding和errors的含義和bytes.decode()類似,用於決定如何將百分號的轉義字符還原爲Unicode字符。

string入參必須爲str類型。

encoding缺省值爲‘utf-8’。errors缺省值爲‘replace’,意味着無效的內容會被佔位符替代。

示例:unquote('/El%20Ni%C3%B1o/') 會返回 '/El Niño/'

urllib.parse.unquote_plus(string, encoding='utf-8', errors='replace')

本函數和unquote()類似,區別在於還原HTML內容的時候會使用空格替換加號。

string入參必須爲str類型。

示例:unquote_plus('/El+Ni%C3%B1o/') 會返回 '/El Niño/'

urllib.parse.unquote_to_bytes(string)

本函數會將%xx形式的轉義字符還原,返回值爲bytes類型。

string入參既可以是str類型,也可以是bytes類型。如果是str類型,非ASCII字符會被還原爲UTF-8的字節序。

示例:unquotetobytes('a%26%EF') 會返回 b'a&\xef'

urllib.parse.urlencode(query, doseq=False, safe='', encoding=None, errors=None, quotevia=quoteplus)

本函數可以將映射對象或者兩元素類型的tuple(其具體值既可以是str,也可以是bytes),轉義爲ASCII類型的文本。如果期望將返回值用於urlopen()來傳遞POST數據,需要先將結果轉爲bytes類型,否則會拋出TypeError異常。

返回值是串通過&符號連接的key=value組合,其中無論是key還是value都已通過入參quotevia轉義。和標準的GET請求(application/x-www-form-urlencoded)兼容,默認情況下,轉義時使用的是quoteplus()函數,這就意味着空格會被轉義爲加號、‘/‘會被轉義爲%2F。另一個可以用於quote_via的轉義函數是quote(),此時會將空格轉義爲%20,並保留‘/’不轉義。如果想要更好的控制轉義規則,建議使用quote函數,並顯式的知名safe入參。

當入參query爲兩元素類型的tuple時,每個tuple成員裏面的第一個元素會被當作key,第二個元素會被當作value。其中value元素可以有多個,此時如果doseq入參爲True,該函數會迭代value,生成多個key=value的組合,將這些組合通過&分割符全部添加到返回值裏面。最終的返回值裏面的參數順序同tuple順序保持一致。

safe、encoding以及errors入參都將透傳給quote_via(當然,只有query入參爲str類型,encoding和errors纔會真正向下透傳)。

parseqs()和parseqsl()可以逆向本函數的編碼過程,將一個query字符串轉換爲Python的數據結構。

 

----------------------------------------------------------------

相關文檔:

RFC 3986-統一資源標識符:該標準爲當前在用的標準。任何urllib.parse模塊的變動都需要參考該標準。某些同標準不一致的地方主要是爲了向後兼容,並和瀏覽器的實際實現保持一致。

RFC 2732-URL中的IPV6地址格式:該標準具體說明了如何解析帶有IPV6的URL

RFC 2396-統一資源標識符--通用格式:該標準介紹了統一資源名(URN)和統一資源定位符(URL)的通用格式。

RFC 2367-mailto的URL協議:該標準解釋了mailto的URL協議

RFC 1808-相對URL:該標準包含如何將拼接絕對URL和相對URL的詳細說明,以及一系列的錯誤示例來展示如何處理邊界值。

RFC 1738-統一資源定位符(URL):該文檔介紹了URL的格式及其含義。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章