urllib.parse
— 将 URL 解析为组件¶
源代码: Lib/urllib/parse.py
此模块定义了一个标准接口,用于将统一资源定位符 (URL) 字符串分解为各个组件(寻址方案、网络位置、路径等),将这些组件重新组合成一个 URL 字符串,并根据“基本 URL”将“相对 URL”转换为绝对 URL。
此模块旨在与关于相对统一资源定位符的互联网 RFC 相匹配。它支持以下 URL 方案:file
、ftp
、gopher
、hdl
、http
、https
、imap
、itms-services
、mailto
、mms
、news
、nntp
、prospero
、rsync
、rtsp
、rtsps
、rtspu
、sftp
、shttp
、sip
、sips
、snews
、svn
、svn+ssh
、telnet
、wais
、ws
、wss
。
CPython 实现细节: 包含 itms-services
URL 方案可能会阻止应用程序通过 Apple macOS 和 iOS App Store 的审核流程。在 iOS 上,itms-services
方案的处理总是会被移除;在 macOS 上,如果 CPython 使用 --with-app-store-compliance
选项构建,则 可能 会被移除。
urllib.parse
模块定义的函数分为两大类:URL 解析和 URL 引用。这些内容将在以下章节中详细介绍。
此模块的函数使用了已弃用的术语 netloc
(或 net_loc
),该术语首次出现在 RFC 1808 中。然而,此术语已被 RFC 3986 废弃,后者引入了术语 authority
作为其替代。出于向后兼容性考虑,netloc
的使用仍在继续。
URL 解析¶
URL 解析函数主要用于将 URL 字符串拆分为其组件,或将 URL 组件组合成一个 URL 字符串。
- urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)¶
将 URL 解析成六个组件,返回一个包含 6 个元素的命名元组。这对应于 URL 的一般结构:
scheme://netloc/path;parameters?query#fragment
。每个元组项都是一个字符串,可能为空。组件不会被分解成更小的部分(例如,网络位置是一个单一的字符串),并且不会展开百分比转义。如上所示的分隔符不属于结果的一部分,除了路径组件中的前导斜杠,如果存在则保留。例如>>> from urllib.parse import urlparse >>> urlparse("scheme://netloc/path;parameters?query#fragment") ParseResult(scheme='scheme', netloc='netloc', path='/path;parameters', params='', query='query', fragment='fragment') >>> o = urlparse("https://docs.pythonlang.cn:80/3/library/urllib.parse.html?" ... "highlight=params#url-parsing") >>> o ParseResult(scheme='http', netloc='docs.python.org:80', path='/3/library/urllib.parse.html', params='', query='highlight=params', fragment='url-parsing') >>> o.scheme 'http' >>> o.netloc 'docs.python.org:80' >>> o.hostname 'docs.python.org' >>> o.port 80 >>> o._replace(fragment="").geturl() 'https://docs.pythonlang.cn:80/3/library/urllib.parse.html?highlight=params'
根据 RFC 1808 中的语法规范,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 未指定时使用。它应该与 urlstring 具有相同类型(文本或字节),但默认值
''
始终允许,并在适当时候自动转换为b''
。如果 allow_fragments 参数为 false,则不识别片段标识符。相反,它们被解析为路径、参数或查询组件的一部分,并且返回值中的
fragment
被设置为空字符串。返回值是一个命名元组,这意味着它的项可以通过索引或命名属性访问,这些属性是
属性
索引
值
如果不存在则返回的值
方案
0
URL 方案说明符
scheme 参数
网络位置
1
网络位置部分
空字符串
路径
2
分层路径
空字符串
参数
3
最后一个路径元素的参数
空字符串
查询
4
查询组件
空字符串
片段
5
片段标识符
空字符串
用户名
用户名
密码
密码
主机名
主机名(小写)
端口
端口号(如果存在,为整数)
如果在 URL 中指定了无效端口,读取
port
属性将引发ValueError
。有关结果对象的更多信息,请参见结构化解析结果部分。netloc
属性中不匹配的方括号将引发ValueError
。netloc
属性中在 NFKC 规范化下(如 IDNA 编码所用)分解为/
、?
、#
、@
或:
任何字符都将引发ValueError
。如果在解析之前 URL 被分解,则不会引发错误。与所有命名元组一样,子类具有一些特别有用的附加方法和属性。其中一个方法是
_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='')
警告
urlparse()
不执行验证。详细信息请参阅URL 解析安全性。3.2 版本中已更改: 增加了 IPv6 URL 解析功能。
3.3 版本中已更改: 现在所有 URL 方案都解析片段(除非 allow_fragments 为 false),这符合 RFC 3986。此前,存在一个支持片段的方案白名单。
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, separator='&')¶
解析作为字符串参数给出的查询字符串(application/x-www-form-urlencoded 类型的数据)。数据以字典形式返回。字典键是唯一的查询变量名,值是每个名称的值列表。
可选参数 keep_blank_values 是一个标志,指示百分号编码查询中的空白值是否应被视为空字符串。真值表示空白应保留为空字符串。默认的假值表示应忽略空白值,并将其视为未包含在内。
可选参数 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 版本中已更改: 添加了 encoding 和 errors 参数。
3.8 版本中已更改: 添加了 max_num_fields 参数。
3.10 版本中已更改: 添加了 separator 参数,默认值为
&
。Python 3.10 之前的版本允许使用;
和&
作为查询参数分隔符。此行为已更改为仅允许单个分隔符键,默认分隔符为&
。自 3.14 版本弃用: 接受除空字符串、字节类对象和
None
之外的假值对象(如0
和[]
)现已弃用。
- 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 是一个标志,指示百分号编码查询中的空白值是否应被视为空字符串。真值表示空白应保留为空字符串。默认的假值表示应忽略空白值,并将其视为未包含在内。
可选参数 strict_parsing 是一个标志,指示如何处理解析错误。如果为 false(默认),则静默忽略错误。如果为 true,则错误会引发
ValueError
异常。可选的 encoding 和 errors 参数指定如何将百分号编码序列解码为 Unicode 字符,这与
bytes.decode()
方法所接受的方式相同。可选参数 max_num_fields 是要读取的最大字段数。如果设置,则如果读取的字段数超过 max_num_fields,则会引发
ValueError
。可选参数 separator 是用于分隔查询参数的符号。它默认为
&
。使用
urllib.parse.urlencode()
函数将此类对列表转换为查询字符串。3.2 版本中已更改: 添加了 encoding 和 errors 参数。
3.8 版本中已更改: 添加了 max_num_fields 参数。
3.10 版本中已更改: 添加了 separator 参数,默认值为
&
。Python 3.10 之前的版本允许使用;
和&
作为查询参数分隔符。此行为已更改为仅允许单个分隔符键,默认分隔符为&
。
- urllib.parse.urlunparse(parts)¶
从
urlparse()
返回的元组构造一个 URL。parts 参数可以是任何六项可迭代对象。这可能会导致 URL 略有不同但等效,如果原始解析的 URL 具有不必要的分隔符(例如,带空查询的?
;RFC 指出这些是等效的)。
- urllib.parse.urlsplit(urlstring, scheme='', allow_fragments=True)¶
这与
urlparse()
类似,但不会将参数从 URL 中分离。如果需要更近的 URL 语法,允许将参数应用于 URL path 部分的每个片段(参见 RFC 2396),则通常应使用此函数而不是urlparse()
。需要一个单独的函数来分离路径片段和参数。此函数返回一个包含 5 个元素的命名元组(addressing scheme, network location, path, query, fragment identifier).
返回值是一个命名元组,它的项可以通过索引或命名属性访问
属性
索引
值
如果不存在则返回的值
方案
0
URL 方案说明符
scheme 参数
网络位置
1
网络位置部分
空字符串
路径
2
分层路径
空字符串
查询
3
查询组件
空字符串
片段
4
片段标识符
空字符串
用户名
用户名
密码
密码
主机名
主机名(小写)
端口
端口号(如果存在,为整数)
如果在 URL 中指定了无效端口,读取
port
属性将引发ValueError
。有关结果对象的更多信息,请参见结构化解析结果部分。netloc
属性中不匹配的方括号将引发ValueError
。netloc
属性中在 NFKC 规范化下(如 IDNA 编码所用)分解为/
、?
、#
、@
或:
任何字符都将引发ValueError
。如果在解析之前 URL 被分解,则不会引发错误。遵循更新 RFC 3986 的 WHATWG 规范 的某些部分,URL 中开头的 C0 控制字符和空格字符将被剥离。URL 中任何位置的
\n
、\r
和制表符\t
字符将被移除。警告
urlsplit()
不执行验证。详细信息请参阅URL 解析安全性。3.6 版本中已更改: 超出范围的端口号现在会引发
ValueError
,而不是返回None
。3.8 版本中已更改: 在 NFKC 规范化下影响 netloc 解析的字符现在会引发
ValueError
。3.10 版本中已更改: ASCII 换行符和制表符从 URL 中去除。
3.12 版本中已更改: URL 中开头的 WHATWG C0 控制字符和空格字符将被剥离。
- urllib.parse.urlunsplit(parts)¶
将
urlsplit()
返回的元组元素组合成一个完整的 URL 字符串。parts 参数可以是任何五项可迭代对象。这可能会导致 URL 略有不同但等效,如果原始解析的 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', ... '//pythonlang.cn/%7Eguido') 'https://pythonlang.cn/%7Eguido'
如果你不想这种行为,请使用
urlsplit()
和urlunsplit()
预处理 url,删除可能的 scheme 和 netloc 部分。警告
由于绝对 URL 可以作为
url
参数传入,因此使用攻击者控制的url
调用urljoin
通常是 不安全 的。例如,在urljoin("https://website.com/users/", username)
中,如果username
可以包含一个绝对 URL,则urljoin
的结果将是该绝对 URL。3.5 版本中已更改: 行为已更新以匹配 RFC 3986 中定义的语义。
- urllib.parse.urldefrag(url)¶
如果 url 包含片段标识符,则返回一个不带片段标识符的修改版 url,并将片段标识符作为单独的字符串。如果 url 中没有片段标识符,则返回未修改的 url 和一个空字符串。
返回值是一个命名元组,它的项可以通过索引或命名属性访问
属性
索引
值
如果不存在则返回的值
网址
0
不带片段的 URL
空字符串
片段
1
片段标识符
空字符串
有关结果对象的更多信息,请参见结构化解析结果部分。
3.2 版本中已更改: 结果是一个结构化对象而不是简单的 2-元组。
- urllib.parse.unwrap(url)¶
从封装的 URL 中提取 URL(即,格式为
<URL:scheme://host/path>
、<scheme://host/path>
、URL:scheme://host/path
或scheme://host/path
的字符串)。如果 url 不是封装的 URL,则原样返回。
URL 解析安全性¶
urlsplit()
和 urlparse()
API 不执行输入 验证。它们可能不会对其他应用程序认为无效的输入引发错误。它们也可能在其他地方可能不被视为 URL 的某些输入上成功。
它们不是在异常输入上引发异常,而是可能返回某些组件部分作为空字符串。或者组件可能包含超出其应有的内容。
我们建议这些 API 的用户,在返回的值可能在任何具有安全隐患的地方使用时,进行防御性编码。在信任返回的组件部分之前,在您的代码中进行一些验证。该 scheme
有意义吗?这是一个合理的 path
吗?那个 hostname
有什么奇怪之处吗?等等。
URL 的构成并未普遍明确定义。不同的应用程序有不同的需求和期望约束。例如,当前的 WHATWG 规范 描述了面向用户的 Web 客户端(如 Web 浏览器)所需的内容。而 RFC 3986 更通用。这些函数结合了两者的某些方面,但不能声称完全符合其中任何一个。API 和现有用户代码对特定行为的期望早于这两个标准,这使得我们对 API 行为的更改非常谨慎。
解析 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 编码的字节序列
结构化解析结果¶
来自 urlparse()
、urlsplit()
和 urldefrag()
函数的结果对象是 tuple
类型的子类。这些子类添加了这些函数文档中列出的属性、上一节中描述的编码和解码支持,以及一个附加方法
- urllib.parse.SplitResult.geturl()¶
以字符串形式返回原始 URL 的重新组合版本。这可能与原始 URL 略有不同,因为方案可能会规范化为小写,并且空组件可能会被删除。具体来说,空参数、查询和片段标识符将被删除。
对于
urldefrag()
结果,只会删除空的片段标识符。对于urlsplit()
和urlparse()
结果,所有注明的更改都将应用于此方法返回的 URL。如果此方法的结果重新通过原始解析函数,则结果保持不变。
>>> from urllib.parse import urlsplit >>> url = 'https://pythonlang.cn/doc/#' >>> r1 = urlsplit(url) >>> r1.geturl() 'https://pythonlang.cn/doc/' >>> r2 = urlsplit(r1.geturl()) >>> r2.geturl() 'https://pythonlang.cn/doc/'
以下类提供了在操作 str
对象时结构化解析结果的实现
- class urllib.parse.DefragResult(url, fragment)¶
包含
str
数据的urldefrag()
结果的具体类。encode()
方法返回一个DefragResultBytes
实例。在 3.2 版本加入。
- class urllib.parse.ParseResult(scheme, netloc, path, params, query, fragment)¶
包含
str
数据的urlparse()
结果的具体类。encode()
方法返回一个ParseResultBytes
实例。
- class urllib.parse.SplitResult(scheme, netloc, path, query, fragment)¶
包含
str
数据的urlsplit()
结果的具体类。encode()
方法返回一个SplitResultBytes
实例。
以下类提供了在操作 bytes
或 bytearray
对象时解析结果的实现
- class urllib.parse.DefragResultBytes(url, fragment)¶
包含
bytes
数据的urldefrag()
结果的具体类。decode()
方法返回一个DefragResult
实例。在 3.2 版本加入。
- class urllib.parse.ParseResultBytes(scheme, netloc, path, params, query, fragment)¶
包含
bytes
数据的urlparse()
结果的具体类。decode()
方法返回一个ParseResult
实例。在 3.2 版本加入。
- class urllib.parse.SplitResultBytes(scheme, netloc, path, query, fragment)¶
包含
bytes
数据的urlsplit()
结果的具体类。decode()
方法返回一个SplitResult
实例。在 3.2 版本加入。
URL 引用¶
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
。如果 string 是bytes
,则不能提供 encoding 和 errors,否则会引发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()
方法所接受的方式相同。encoding 默认为
'utf-8'
。errors 默认为'replace'
,这意味着无效序列将替换为占位符字符。示例:
unquote('/El%20Ni%C3%B1o/')
得到'/El Niño/'
。3.9 版本中已更改: string 参数支持字节和字符串对象(以前只支持字符串)。
- 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
,则 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 文本字符串。如果生成的字符串要用作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 指定一个值。当两元素元组序列用作 query 参数时,每个元组的第一个元素是键,第二个元素是值。值元素本身可以是一个序列,在这种情况下,如果可选参数 doseq 评估为
True
,则对于键的值序列的每个元素,将生成由'&'
分隔的单独key=value
对。编码字符串中参数的顺序将与序列中参数元组的顺序匹配。safe、encoding 和 errors 参数传递给 quote_via(encoding 和 errors 参数仅在查询元素为
str
时传递)。要反转此编码过程,此模块中提供了
parse_qs()
和parse_qsl()
,用于将查询字符串解析为 Python 数据结构。请参阅 urllib 示例,了解如何使用
urllib.parse.urlencode()
方法生成 URL 的查询字符串或 POST 请求的数据。3.2 版本中已更改: query 支持字节和字符串对象。
3.5 版本中已更改: 添加了 quote_via 参数。
自 3.14 版本弃用: 接受除空字符串、字节类对象和
None
之外的假值对象(如0
和[]
)现已弃用。
参见
- WHATWG - URL 实时标准
URL 标准工作组,定义 URL、域名、IP 地址、application/x-www-form-urlencoded 格式及其 API。
- RFC 3986 - 统一资源标识符
这是当前的标准 (STD66)。对 urllib.parse 模块的任何更改都应符合此标准。可能会观察到某些偏差,这主要是为了向后兼容性以及主要浏览器中常见的某些事实上的解析要求。
- RFC 2732 - URL 中 IPv6 字面地址的格式。
这指定了 IPv6 URL 的解析要求。
- RFC 2396 - 统一资源标识符 (URI):通用语法
描述统一资源名称(URN)和统一资源定位符(URL)通用语法要求的文档。
- RFC 2368 - mailto URL 方案。
mailto URL 方案的解析要求。
- RFC 1808 - 相对统一资源定位符
这份请求评论(Request For Comments)包含了用于连接绝对URL和相对URL的规则,其中包括大量用于处理边界情况的“异常示例”。
- RFC 1738 - 统一资源定位符 (URL)
这规定了绝对URL的正式语法和语义。