21.8. urllib.parse — 将 URL 解析为组件 — Python 文档
21.8. urllib.parse — 将 URL 解析为组件
源代码: :source:`Lib/urllib/parse.py`
该模块定义了一个标准接口来分解组件(寻址方案、网络位置、路径等)中的统一资源定位器 (URL) 字符串,将组件组合回 URL 字符串,并将“相对 URL”转换为给定“基本 URL”的绝对 URL。
该模块旨在匹配 Internet RFC 上的相对统一资源定位符。 它支持以下 URL 方案:file
、ftp
、gopher
、hdl
、http
、https
、[ X105X]、mailto
、mms
、news
、nntp
、prospero
、rsync
]、rtspu
、sftp
、shttp
、sip
、sips
、、[X272X] 、svn+ssh
、telnet
、wais
、ws
、wss
。
urllib.parse 模块定义了分为两大类的函数:URL 解析和 URL 引用。 以下各节将详细介绍这些内容。
21.8.1. 网址解析
URL 解析函数专注于将 URL 字符串拆分为其组件,或将 URL 组件组合为 URL 字符串。
- urllib.parse.urlparse(urlstring, scheme=, allow_fragments=True)
将 URL 解析为六个组件,返回一个 6 元组。 这对应于 URL 的一般结构:
scheme://netloc/path;parameters?query#fragment
。 每个元组项都是一个字符串,可能为空。 组件没有分解成更小的部分(例如,网络位置是单个字符串),并且 % escapes 没有展开。 上面显示的分隔符不是结果的一部分,除了 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 中的语法规范,urlparse 仅在由“//”正确引入时才识别 netloc。 否则,输入被假定为相对 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
被设置为返回值中的空字符串。返回值实际上是 tuple 的一个子类的实例。 此类具有以下额外的只读便利属性:
属性
指数
价值
值如果不存在
scheme
0
URL 方案说明符
方案参数
netloc
1
网络定位部分
空字符串
path
2
分层路径
空字符串
params
3
最后一个路径元素的参数
空字符串
query
4
查询组件
空字符串
fragment
5
片段标识符
空字符串
username
用户名
password
密码
hostname
主机名(小写)
port
端口号为整数(如果存在)
如果 URL 中指定了无效端口,则读取
port
属性将引发 ValueError。 有关结果对象的更多信息,请参阅 结构化解析结果 部分。netloc
属性中不匹配的方括号将引发 ValueError。netloc
属性中的字符在 NFKC 规范化(如 IDNA 编码所使用)下分解为/
、?
、#
、@
或:
将引发 ValueError。 如果在解析之前将 URL 分解,则不会引发错误。3.2 版更改: 添加 IPv6 URL 解析功能。
3.3 版更改: 现在根据 RFC 3986 解析所有 URL 方案的片段(除非 allow_fragment 为 false) . 以前,存在支持片段的方案白名单。
3.6 版更改: 超出范围的端口号现在会引发 ValueError,而不是返回 None。
在 3.6.9 版更改:影响 NFKC 规范化下的 netloc 解析的字符现在将引发 ValueError。
- urllib.parse.parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None, separator='&')
解析作为字符串参数给出的查询字符串(application/x-www-form-urlencoded 类型的数据)。 数据作为字典返回。 字典键是唯一的查询变量名称,值是每个名称的值列表。
可选参数 keep_blank_values 是一个标志,指示百分比编码查询中的空白值是否应视为空白字符串。 真值表示应将空白保留为空白字符串。 默认 false 值表示将忽略空白值并将其视为不包括在内。
可选参数 strict_parsing 是一个标志,指示如何处理解析错误。 如果为 false(默认值),错误将被静默忽略。 如果为 true,则错误会引发 ValueError 异常。
可选的 encoding 和 errors 参数指定如何将百分比编码的序列解码为 Unicode 字符,如 bytes.decode() 方法所接受。
可选参数 max_num_fields 是要读取的最大字段数。 如果设置,则在读取的字段超过 max_num_fields 时抛出 ValueError。
可选参数 separator 是用于分隔查询参数的符号。 默认为
&
。使用 urllib.parse.urlencode() 函数(将
doseq
参数设置为True
)将此类字典转换为查询字符串。3.2 版更改: 添加 编码 和 错误 参数。
3.6.8 版更改: 添加 max_num_fields 参数。
3.6.13 版本更改: 添加 分隔符 参数,默认值为
&
。 Python 3.6.13 之前的 Python 版本允许同时使用;
和&
作为查询参数分隔符。 这已更改为仅允许单个分隔符键,&
作为默认分隔符。
- urllib.parse.parse_qsl(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None, separator='&')
解析作为字符串参数给出的查询字符串(application/x-www-form-urlencoded 类型的数据)。 数据以名称、值对列表的形式返回。
可选参数 keep_blank_values 是一个标志,指示百分比编码查询中的空白值是否应视为空白字符串。 真值表示应将空白保留为空白字符串。 默认 false 值表示将忽略空白值并将其视为不包括在内。
可选参数 strict_parsing 是一个标志,指示如何处理解析错误。 如果为 false(默认值),错误将被静默忽略。 如果为 true,则错误会引发 ValueError 异常。
可选的 encoding 和 errors 参数指定如何将百分比编码的序列解码为 Unicode 字符,如 bytes.decode() 方法所接受。
可选参数 max_num_fields 是要读取的最大字段数。 如果设置,则在读取的字段超过 max_num_fields 时抛出 ValueError。
可选参数 separator 是用于分隔查询参数的符号。 默认为
&
。使用 urllib.parse.urlencode() 函数将此类对列表转换为查询字符串。
3.2 版更改: 添加 编码 和 错误 参数。
3.6.8 版更改: 添加 max_num_fields 参数。
3.6.13 版本更改: 添加 分隔符 参数,默认值为
&
。 Python 3.6.13 之前的 Python 版本允许同时使用;
和&
作为查询参数分隔符。 这已更改为仅允许单个分隔符键,&
作为默认分隔符。
- urllib.parse.urlunparse(parts)
- 从
urlparse()
返回的元组构造 URL。 parts 参数可以是任何六项可迭代的。 如果最初解析的 URL 具有不必要的分隔符(例如,带有空查询的?
;RFC 声明它们是等效的),这可能会导致略有不同但等效的 URL。
- urllib.parse.urlsplit(urlstring, scheme=, allow_fragments=True)
这类似于 urlparse(),但不会从 URL 中分离参数。 如果更新的 URL 语法允许将参数应用于 URL 的 path 部分的每个段,则通常应使用它代替 urlparse()(请参阅 ]RFC 2396) 是需要的。 需要一个单独的函数来分隔路径段和参数。 此函数返回一个 5 元组:(寻址方案、网络位置、路径、查询、片段标识符)。
返回值实际上是 tuple 的一个子类的实例。 此类具有以下额外的只读便利属性:
属性
指数
价值
值如果不存在
scheme
0
URL 方案说明符
方案参数
netloc
1
网络定位部分
空字符串
path
2
分层路径
空字符串
query
3
查询组件
空字符串
fragment
4
片段标识符
空字符串
username
用户名
password
密码
hostname
主机名(小写)
port
端口号为整数(如果存在)
如果 URL 中指定了无效端口,则读取
port
属性将引发 ValueError。 有关结果对象的更多信息,请参阅 结构化解析结果 部分。netloc
属性中不匹配的方括号将引发 ValueError。netloc
属性中的字符在 NFKC 规范化(如 IDNA 编码所使用)下分解为/
、?
、#
、@
或:
将引发 ValueError。 如果在解析之前将 URL 分解,则不会引发错误。遵循更新 RFC 3986 的 WHATWG 规范 ,ASCII 换行符
\n
、\r
和制表符\t
字符从 URL 中删除。3.6 版更改: 超出范围的端口号现在会引发 ValueError,而不是返回 None。
在 3.6.9 版更改:影响 NFKC 规范化下的 netloc 解析的字符现在将引发 ValueError。
3.6.14 版更改:ASCII 换行符和制表符从 URL 中删除。
- urllib.parse.urlunsplit(parts)
- 将 urlsplit() 返回的元组元素组合成一个完整的 URL 作为字符串。 parts 参数可以是任何五项可迭代的。 如果最初解析的 URL 具有不必要的分隔符(例如,一个 ? 带有空查询; RFC 声明这些是等效的)。
- urllib.parse.urljoin(base, url, allow_fragments=True)
通过将“基本 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() 具有相同的含义和默认值。
笔记
如果 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 和空字符串。
返回值实际上是 tuple 的一个子类的实例。 此类具有以下额外的只读便利属性:
属性
指数
价值
值如果不存在
url
0
没有片段的网址
空字符串
fragment
1
片段标识符
空字符串
有关结果对象的更多信息,请参阅 结构化解析结果 部分。
3.2 版更改: 结果是结构化对象,而不是简单的 2 元组。
21.8.2. 解析 ASCII 编码字节
URL 解析函数最初设计为仅对字符串进行操作。 在实践中,能够将正确引用和编码的 URL 作为 ASCII 字节序列进行操作是很有用的。 因此,本模块中的 URL 解析函数除了对 str 对象之外,还对 bytes 和 bytearray 对象进行操作。
如果传入 str 数据,结果也将只包含 str 数据。 如果传入 bytes 或 bytearray 数据,则结果将仅包含 bytes 数据。
尝试在单个函数调用中将 str 数据与 bytes 或 bytearray 混合将导致 TypeError 被引发,同时试图通过在非 ASCII 字节值中将触发 UnicodeDecodeError。
为了支持在 str 和 bytes 之间更轻松地转换结果对象,URL 解析函数的所有返回值都提供 encode()
方法(当结果包含 str 数据)或 decode()
方法(当结果包含 bytes 数据时)。 这些方法的签名与相应的 str 和 bytes 方法的签名相匹配(除了默认编码是 'ascii'
而不是 'utf-8'
)。 每个产生一个相应类型的值,其中包含 bytes 数据(对于 encode()
方法)或 str 数据(对于 decode()
方法)。
需要对可能包含非 ASCII 数据的潜在不正确引用的 URL 进行操作的应用程序将需要在调用 URL 解析方法之前自己进行从字节到字符的解码。
本节中描述的行为仅适用于 URL 解析函数。 URL 引用函数在生成或使用字节序列时使用自己的规则,如各个 URL 引用函数的文档中所述。
3.2 版更改:URL 解析函数现在接受 ASCII 编码的字节序列
21.8.3. 结构化解析结果
来自 urlparse()、urlsplit() 和 urldefrag() 函数的结果对象是 tuple 类型的子类。 这些子类添加了这些函数的文档中列出的属性、上一节中描述的编码和解码支持,以及一个附加方法:
- urllib.parse.SplitResult.geturl()
将原始 URL 的重新组合版本作为字符串返回。 这可能与原始 URL 不同,因为该方案可能被规范化为小写,并且可能会删除空组件。 具体来说,空参数、查询和片段标识符将被删除。
对于 urldefrag() 结果,只会删除空片段标识符。 对于 urlsplit() 和 urlparse() 结果,将对此方法返回的 URL 进行所有注意到的更改。
如果通过原始解析函数返回,则此方法的结果保持不变:
>>> 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)
urldefrag() 结果的具体类包含 str 数据。
encode()
方法返回一个 DefragResultBytes 实例。3.2 版中的新功能。
- 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 或 bytearray 对象进行操作时解析结果的实现:
- class urllib.parse.DefragResultBytes(url, fragment)
urldefrag() 结果的具体类包含 bytes 数据。
decode()
方法返回一个 DefragResult 实例。3.2 版中的新功能。
- class urllib.parse.ParseResultBytes(scheme, netloc, path, params, query, fragment)
urlparse() 结果的具体类包含 bytes 数据。
decode()
方法返回一个 ParseResult 实例。3.2 版中的新功能。
- class urllib.parse.SplitResultBytes(scheme, netloc, path, query, fragment)
urlsplit() 结果的具体类包含 bytes 数据。
decode()
方法返回一个 SplitResult 实例。3.2 版中的新功能。
21.8.4. 网址引用
URL 引用函数专注于获取程序数据,并通过引用特殊字符和适当编码非 ASCII 文本使其安全地用作 URL 组件。 如果上述 URL 解析函数尚未涵盖该任务,则它们还支持反转这些操作以从 URL 组件的内容重新创建原始数据。
- urllib.parse.quote(string, safe='/', encoding=None, errors=None)
使用
%xx
转义替换 string 中的特殊字符。 从不引用字母、数字和字符'_.-'
。 默认情况下,此函数用于引用 URL 的路径部分。 可选的 safe 参数指定不应被引用的其他 ASCII 字符——其默认值为'/'
。可选的 encoding 和 errors 参数指定如何处理非 ASCII 字符,由 str.encode() 方法接受。 encoding 默认为
'utf-8'
。 errors 默认为'strict'
,这意味着不支持的字符会引发 UnicodeEncodeError。 encoding 和 errors 如果 string 是 bytes,或者 TypeError 被提出,则不得提供。请注意,
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 参数指定如何将百分比编码的序列解码为 Unicode 字符,如 bytes.decode() 方法所接受。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 对象。如果是 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)
将可能包含 str 或 bytes 对象的映射对象或二元素元组序列转换为百分比编码的 ASCII 文本字符串。 如果将结果字符串用作 data 用于使用 urlopen() 函数进行 POST 操作,则应将其编码为字节,否则将导致 类型错误。
结果字符串是一系列由
'&'
字符分隔的key=value
对,其中 key 和 value 都使用 quote_via[ X164X] 功能。 默认情况下,quote_plus() 用于引用值,这意味着空格被引用为'+'
字符,'/' 字符被编码为%2F
,如下所示GET 请求的标准 (application/x-www-form-urlencoded
)。 可以作为 quote_via 传递的替代函数是 quote(),它将空格编码为%20
而不会编码“/”字符。 为了最大限度地控制引用的内容,请使用quote
并为 safe 指定一个值。当一个双元素元组序列用作 query 参数时,每个元组的第一个元素是一个键,第二个是一个值。 值元素本身可以是一个序列,在这种情况下,如果可选参数 doseq 的计算结果为
True
,单个key=value
对由'&'
分隔] 是为键的值序列的每个元素生成的。 编码字符串中参数的顺序将与序列中参数元组的顺序匹配。safe、encoding 和 errors 参数被传递给 quote_via(encoding 和 errors 参数仅在查询元素是 str 时传递。
为了反转这个编码过程,这个模块中提供了 parse_qs() 和 parse_qsl() 来将查询字符串解析为 Python 数据结构。
请参阅 urllib 示例 以了解如何使用 urlencode 方法为 URL 或 POST 数据生成查询字符串。
3.2 版更改: 查询参数支持字节和字符串对象。
3.5 新功能:quote_via 参数。
也可以看看
- WHATWG - URL 生活标准
- 定义 URL、域、IP 地址、application/x-www-form-urlencoded 格式及其 API 的 URL 标准工作组。
- RFC 3986 - 统一资源标识符
- 这是当前的标准 (STD66)。 对 urllib.parse 模块的任何更改都应符合此要求。 可以观察到某些偏差,这主要是出于向后兼容性目的以及在主要浏览器中常见的某些事实上的解析要求。
- RFC 2732 - URL 中文字 IPv6 地址的格式。
- 这指定了 IPv6 URL 的解析要求。
- RFC 2396 - 统一资源标识符 (URI):通用语法
- 描述统一资源名称 (URN) 和统一资源定位符 (URL) 的通用句法要求的文档。
- RFC 2368 - mailto URL 方案。
- mailto URL 方案的解析要求。
- RFC 1808 - 相对统一资源定位符
- 此征求意见稿包括加入绝对和相对 URL 的规则,包括相当数量的“异常示例”,这些“异常示例”管理边界案例的处理。
- RFC 1738 - 统一资源定位符 (URL)
- 这指定了绝对 URL 的正式语法和语义。