urllib.parse —将 URL 解析为组件

源代码: Lib/urllib/parse.py


该模块定义了一个标准接口,用于分解组件中的统一资源定位符(URL)字符串(寻址方案,网络位置,路径等),将组件组合回 URL 字符串,并将“相对 URL”转换为指定了“基本 URL”的绝对 URL。

设计该模块以匹配相对统一资源定位符上的 Internet RFC。它支持以下 URL 方案:fileftpgopherhdlhttphttpsimapmailtommsnewsnntpprosperorsyncrtsprtspusftpshttpsip _21 ,telnetwaiswswss

urllib.parse模块定义的Function分为两大类:URL 解析和 URL 引用。以下各节将详细介绍这些内容。

URL Parsing

URL 解析Function着重于将 URL 字符串拆分为其组件,或将 URL 组件组合为 URL 字符串。

  • urllib.parse. urlparse(* urlstring scheme ='' allow_fragments = True *)
    • 将 URL 解析为六个部分,返回 6 个项named tuple。这对应于 URL 的一般结构:scheme://netloc/path;parameters?query#fragment。每个 Tuples 项目都是一个字符串,可能为空。组件不会分成较小的部分(例如,网络位置是单个字符串),并且%转义符不会扩展。上面显示的定界符不是结果的一部分,除了* path *组件中的前导斜线(如果存在的话,将保留)。例如:
>>> from urllib.parse import urlparse
>>> o = urlparse('http://www.cwi.nl:80/%7Eguido/Python.html')
>>> o   
ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',
            params='', query='', fragment='')
>>> o.scheme
'http'
>>> o.port
80
>>> o.geturl()
'http://www.cwi.nl:80/%7Eguido/Python.html'

遵循 RFC 1808中的语法规范,仅当'//'正确引入 netloc 时,urlparse 才识别它。否则,假定 Importing 为相对 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 未指定一个方案时使用。它的类型(文本或字节)应与 urlstring *相同,除了始终允许默认值''并在适当时自动将其转换为b''

如果* allow_fragments *参数为 false,则无法识别片段标识符。而是将它们解析为路径,参数或查询组件的一部分,并将fragment设置为返回值中的空字符串。

返回值为named tuple,这意味着它的项目可以pass索引或作为命名属性来访问,它们是:

AttributeIndexValue值(如果不存在)
scheme0URL 方案说明符* scheme *参数
netloc1网络位置部分empty string
path2Hierarchical pathempty string
params3最后路径元素的参数empty string
query4Query componentempty string
fragment5Fragment identifierempty string
usernameUser nameNone
passwordPasswordNone
hostname主机名(小写)None
port端口号为整数(如果存在)None

如果在 URL 中指定了无效的端口,则读取port属性将引发ValueError。有关结果对象的更多信息,请参见结构化解析结果部分。

netloc属性中不匹配的方括号将引发ValueError

netloc属性中的字符在 NFKC 规范下(由 IDNA 编码使用)分解为/?#@:中的任何一个,将引发ValueError。如果在解析之前将 URL 分解,则不会引发任何错误。

与所有命名 Tuples 一样,该子类还具有一些特别有用的附加方法和属性。一种这样的方法是_replace()_replace()方法将返回一个新的 ParseResult 对象,用新值替换指定的字段。

>>> 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='')

在版本 3.2 中进行了更改:添加了 IPv6 URL 解析Function。

在版本 3.3 中更改:现在按照 RFC 3986解析所有 URL 方案的片段(除非* allow_fragment *为 false)。以前,存在支持片段的方案白名单。

在版本 3.6 中进行了更改:超出范围的端口号现在提高ValueError,而不是返回None

在版本 3.8 中进行了更改:在 NFKC 规范化下影响 netloc 解析的字符现在将引发ValueError

  • 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 *的数据)。数据作为字典返回。字典键是唯一的查询变量名称,而值是每个名称的值列表。

可选参数* keep_blank_values *是一个标志,指示是否应将百分比编码的查询中的空白值视为空白字符串。真值表示应将空格保留为空白字符串。默认的 false 值指示将忽略空白值并将其视为未包含空白值。

可选参数* strict_parsing *是一个标志,指示如何处理解析错误。如果为 false(默认值),错误将被忽略。如果为 true,则错误会引发ValueError异常。

可选的* encoding errors *参数指定如何将百分比编码的序列解码为bytes.decode()方法接受的 Unicode 字符。

可选参数* max_num_fields 是要读取的最大字段数。如果设置,则如果读取的 max_num_fields *个字段以上,则抛出ValueError

使用urllib.parse.urlencode()函数(将doseq参数设置为True)将此类词典转换为查询字符串。

在版本 3.2 中更改:添加* encoding errors *参数。

在 3.8 版中进行了更改:添加了* max_num_fields *参数。

  • 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 *的数据)。数据作为名称,值对的列表返回。

可选参数* keep_blank_values *是一个标志,指示是否应将百分比编码的查询中的空白值视为空白字符串。真值表示应将空格保留为空白字符串。默认的 false 值指示将忽略空白值并将其视为未包含空白值。

可选参数* strict_parsing *是一个标志,指示如何处理解析错误。如果为 false(默认值),错误将被忽略。如果为 true,则错误会引发ValueError异常。

可选的* encoding errors *参数指定如何将百分比编码的序列解码为bytes.decode()方法接受的 Unicode 字符。

可选参数* max_num_fields 是要读取的最大字段数。如果设置,则如果读取的 max_num_fields *个字段以上,则抛出ValueError

使用urllib.parse.urlencode()函数将这样的配对列表转换为查询字符串。

在版本 3.2 中更改:添加* encoding errors *参数。

在 3.8 版中进行了更改:添加了* max_num_fields *参数。

  • urllib.parse. urlunparse(* parts *)

    • 根据urlparse()返回的 Tuples 构造 URL。 * parts *参数可以是任何六项可迭代的。如果最初解析的 URL 包含不必要的定界符(例如,带有空查询的?; RFC 语句它们是等效的),则这可能会导致稍微不同但等效的 URL。
  • urllib.parse. urlsplit(* urlstring scheme ='' allow_fragments = True *)

    • 这类似于urlparse(),但不会从 URL 拆分参数。如果需要将参数应用于 URL 的* path *部分的每个段(请参见 RFC 2396)的最新 URL 语法,通常应使用urlparse()代替。需要单独的Function来分隔路径段和参数。此函数返回 5 项named tuple
(addressing scheme, network location, path, query, fragment identifier).

返回值为named tuple,其项可以pass索引或作为命名属性进行访问:

AttributeIndexValue值(如果不存在)
scheme0URL 方案说明符* scheme *参数
netloc1网络位置部分empty string
path2Hierarchical pathempty string
query3Query componentempty string
fragment4Fragment identifierempty string
usernameUser nameNone
passwordPasswordNone
hostname主机名(小写)None
port端口号为整数(如果存在)None

如果在 URL 中指定了无效的端口,则读取port属性将引发ValueError。有关结果对象的更多信息,请参见结构化解析结果部分。

netloc属性中不匹配的方括号将引发ValueError

netloc属性中的字符在 NFKC 规范下(由 IDNA 编码使用)分解为/?#@:中的任何一个,将引发ValueError。如果在解析之前将 URL 分解,则不会引发任何错误。

在版本 3.6 中进行了更改:超出范围的端口号现在提高ValueError,而不是返回None

在版本 3.8 中进行了更改:在 NFKC 规范化下影响 netloc 解析的字符现在将引发ValueError

  • urllib.parse. urlunsplit(* parts *)

    • urlsplit()返回的 Tuples 元素合并为完整的 URL 作为字符串。 * parts *参数可以是任何五项可迭代的。如果最初解析的 URL 包含不必要的定界符(例如,带空查询的?; RFC 语句它们是等效的),则这可能会导致稍微不同但等效的 URL。
  • urllib.parse. urljoin(* base url allow_fragments = True *)

    • pass将“基本 URL”(* base )与另一个 URL( url *)组合来构造完整的(“绝对”)URL。非正式地,这使用基本 URL 的组件,特别是寻址方案,网络位置和路径(的一部分)来提供相对 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()相同。

Note

如果* url 是绝对 URL(即以//scheme://开头),则 url *的主机名和/或方案将出现在结果中。例如:

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

如果您不希望出现这种情况,请使用urlsplit()urlunsplit()预处理* url ,并删除可能的 scheme netloc *部分。

在版本 3.5 中进行了更改:更新了行为以匹配 RFC 3986中定义的语义。

  • urllib.parse. urldefrag(* url *)
    • 如果* url 包含片段标识符,则返回 url 的修改版本,不包含片段标识符,并将片段标识符作为单独的字符串。如果 url 中没有片段标识符,则返回 url *未经修改且为空字符串。

返回值为named tuple,其项可以pass索引或作为命名属性进行访问:

AttributeIndexValue值(如果不存在)
url0没有片段的 URLempty string
fragment1Fragment identifierempty string

有关结果对象的更多信息,请参见结构化解析结果部分。

在版本 3.2 中更改:结果是结构化对象,而不是简单的 2Tuples。

  • urllib.parse. unwrap(* url *)
    • 从包装的 URL(即,格式为<URL:scheme://host/path><scheme://host/path>URL:scheme://host/pathscheme://host/path的字符串)中提取 URL。如果* url *不是包装的 URL,则返回它而不会更改。

解析 ASCII 编码的字节

URL 解析Function最初旨在仅对字符串进行操作。实际上,能够将正确引用和编码的 URL 作为 ASCII 字节序列进行操作非常有用。因此,除了str对象之外,此模块中的 URL 解析Function都对bytesbytearray对象进行操作。

如果传入str数据,则结果还将仅包含str数据。如果传入bytesbytearray数据,则结果将仅包含bytes数据。

try在单个函数调用中将str数据与bytesbytearray混合将导致TypeError升高,而try传递非 ASCII 字节值将触发UnicodeDecodeError

为了支持在strbytes之间更容易地转换结果对象,URL 解析函数的所有返回值都提供encode()方法(当结果包含str数据时)或decode()方法(当结果包含bytes数据时)。这些方法的签名与相应的strbytes方法的签名匹配(除了默认编码是'ascii'而不是'utf-8')。每个产生一个对应类型的值,该值包含bytes数据(对于encode()方法)或str数据(对于decode()方法)。

需要在可能包含非 ASCII 数据的引用不正确的 URL 上进行操作的应用程序,在调用 URL 解析方法之前,需要先进行从字节到字符的解码。

本节中描述的行为仅适用于 URL 解析Function。 URL 引用函数在生成或使用字节序列时会使用其自己的规则,如单个 URL 引用函数的文档中所述。

在版本 3.2 中进行了更改:URL 解析Function现在可以接受 ASCII 编码的字节序列

结构化解析结果

urlparse()urlsplit()urldefrag()函数的结果对象是tuple类型的子类。这些子类添加了文档中列出的这些Function的属性,上一节中描述的编码和解码支持以及其他方法:

  • urllib.parse.SplitResult. geturl ( )
    • 以字符串形式返回原始 URL 的重新组合版本。这可能与原始 URL 有所不同,因为该方案可以规范化为小写形式,并且可以丢弃空组件。具体来说,将删除空参数,查询和片段标识符。

对于urldefrag()个结果,将仅删除空的片段标识符。对于urlsplit()urlparse()结果,将对此方法返回的 URL 进行所有记录的更改。

如果pass原始解析函数返回,则此方法的结果保持不变:

>>> from urllib.parse import urlsplit
>>> url = 'HTTP://www.Python.org/doc/#'
>>> r1 = urlsplit(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 *)

3.2 版中的新Function。

    • class * urllib.parse. ParseResult(* scheme netloc path params query fragment *)
    • class * urllib.parse. SplitResult(* scheme netloc path query fragment *)

以下类提供了对bytesbytearray对象进行操作时解析结果的实现:

    • class * urllib.parse. DefragResultBytes(* url fragment *)

3.2 版中的新Function。

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

3.2 版中的新Function。

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

3.2 版中的新Function。

URL Quoting

URL 引用Function着重于获取程序数据并pass引用特殊字符并适当地编码非 ASCII 文本来使其安全地用作 URL 组件。如果上面的 URL 解析Function尚未涵盖该任务,它们还支持逆转这些操作以从 URL 组件的内容重新创建原始数据。

  • urllib.parse. quote(* string safe ='/' encoding = None errors = None *)
    • 使用%xx转义符替换* string 中的特殊字符。字母,数字和字符'_.-~'都不会被引用。默认情况下,此函数用于引用 URL 的路径部分。可选的 safe *参数指定不应加引号的其他 ASCII 字符-其默认值为'/'

在 3.7 版中进行了更改:从 RFC 2396移至 RFC 3986以引用 URL 字符串。现在,“~”已包含在一组未保留的字符中。

可选的* encoding errors *参数指定如何处理str.encode()方法接受的非 ASCII 字符。 * encoding 默认为'utf-8'错误默认为'strict',表示不受支持的字符引发UnicodeEncodeError。如果 string bytes或引发TypeError,则不得提供 encoding errors *。

请注意,quote(string, safe, encoding, errors)等效于quote_from_bytes(string.encode(encoding, errors), safe)

示例:quote('/El Niño/')产生'/El%20Ni%C3%B1o/'

  • urllib.parse. quote_plus(* string safe ='' encoding = None errors = None *)
    • 类似于quote(),但也需要用加号替换空格,这是在构建查询字符串以进入 URL 时引用 HTML 表单值所必需的。原始字符串中的加号会转义,除非它们包含在* safe 中。它也没有 safe *默认为'/'

示例:quote_plus('/El Niño/')产生'%2FEl+Ni%C3%B1o%2F'

  • urllib.parse. quote_from_bytes(* bytes safe ='/'*)
    • 类似于quote(),但是接受bytes对象而不是str,并且不执行字符串到字节的编码。

示例:quote_from_bytes(b'a&\xef')产生'a%26%EF'

  • urllib.parse. unquote(* string encoding ='utf-8' errors ='replace'*)
    • 用其单字符等效项替换%xx转义。可选的* encoding errors *参数指定如何将百分比编码的序列解码为bytes.decode()方法接受的 Unicode 字符。
  • string *必须为str

编码默认为'utf-8'错误默认为'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对象。

如果它是str,则* string *中未转义的非 ASCII 字符将编码为 UTF-8 字节。

示例:unquote_to_bytes('a%26%EF')产生b'a&\xef'

  • urllib.parse. urlencode(* query doseq = False safe ='' encoding = None errors = None quote_via = quote_plus *)
    • 将 Map 对象或可能包含strbytes对象的两个元素的 Tuples 序列转换为百分比编码的 ASCII 文本字符串。如果将结果字符串用作urlopen()函数的 POST 操作的* data *,则应将其编码为字节,否则将导致TypeError

结果字符串是由'&'个字符分隔的一系列key=value对,其中* key value 都使用 quote_via 函数引用。默认情况下,quote_plus()用于引用值,这意味着空格用'+'字符引用,'/'字符用%2F编码,这遵循 GET 请求的标准(application/x-www-form-urlencoded)。可以作为 quote_via 传递的替代函数是quote(),它将空格编码为%20而不编码'/'字符。为了最大程度地控制引用的内容,请使用quote并为 safe *指定一个值。

当一个由两个元素组成的 Tuples 序列用作* query 参数时,每个 Tuples 的第一个元素是键,第二个是值。值元素本身可以是一个序列,在这种情况下,如果可选参数 doseq *的值为True,则为键值序列的每个元素生成由'&'分隔的各个key=value对。编码字符串中参数的 Sequences 将与序列中参数 Tuples 的 Sequences 匹配。

  • safe encoding errors 参数向下传递给 quote_via (仅当查询元素为str时才传递 encoding errors *参数)。

为了反转此编码过程,此模块中提供了parse_qs()parse_qsl(),以将查询字符串解析为 Python 数据结构。

请参阅urllib examples,了解如何使用 urlencode 方法生成 URL 的查询字符串或 POST 的数据。

在版本 3.2 中更改:查询参数支持字节和字符串对象。

3.5 版中的新Function:* quote_via *参数。

See also

  • RFC 3986-统一资源标识符

  • 这是当前标准(STD66)。对 urllib.parse 模块的任何更改都应符合此要求。可以观察到某些偏差,主要是出于向后兼容的目的以及某些主要浏览器中常见的实际解析要求。

  • RFC 2732-URL 中 LiteralsIPv6 地址的格式。

  • 这指定了 IPv6 URL 的解析要求。

  • RFC 2396-统一资源标识符(URI):通用语法

  • 描述统一资源名称(URN)和统一资源定位符(URL)的通用语法要求的文档。

  • RFC 2368-mailto URL 方案。

  • mailto URL 方案的解析要求。

  • RFC 1808-相对统一资源定位符

  • 该征求意见书包括连接绝对 URL 和相对 URL 的规则,其中包括相当数量的“异常示例”,用于 Management 边境案件的处理。

  • RFC 1738-统一资源定位符(URL)

  • 这指定了绝对 URL 的形式语法和语义。