urllib.parse.urljoin 是 Python 标准库 urllib.parse 模块中的一个非常有用的函数,它的核心作用是将一个相对 URL(relative URL)与一个基础 URL(base URL)拼接起来,生成一个完整的、绝对 URL。

它解决了在网页开发、爬虫等场景中,处理各种链接路径的烦恼。
核心功能:智能拼接
想象一下,你在浏览一个网站,页面上有一个链接 /about,这个链接是相对于你当前正在访问的页面的,如果你当前在 https://www.example.com/index.html,/about 指向的就是 https://www.example.com/about,如果当前在 https://www.example.com/blog/2025/post.html,/about 指向的仍然是 https://www.example.com/about。
urljoin 就能智能地处理这些情况,它不是简单地用字符串拼接,而是遵循 URL 的标准规范。
语法
from urllib.parse import urljoin urllib.parse.urljoin(base_url, relative_url)
base_url: 基础 URL,通常是当前页面的 URL。relative_url: 需要拼接的相对 URL,可以是路径、也可以是另一个完整的 URL。
详细示例与行为解析
让我们通过一系列例子来彻底理解它的行为,假设我们的 base_url 是 https://www.example.com/base/page.html。

情况1:相对路径
这是最常见的用法。
from urllib.parse import urljoin base = "https://www.example.com/base/page.html" print(urljoin(base, "about.html")) # 输出: https://www.example.com/base/about.html print(urljoin(base, "contact/")) # 输出: https://www.example.com/base/contact/ print(urljoin(base, "images/logo.png")) # 输出: https://www.example.com/base/images/logo.png
解析:当相对 URL 以 开头(或者在 base_url 的路径后面拼接)时,它被视为相对于 base_url 的路径。
情况2:以 开头的路径(返回上一级目录)
from urllib.parse import urljoin base = "https://www.example.com/base/page.html" print(urljoin(base, "../index.html")) # 输出: https://www.example.com/index.html print(urljoin(base, "../../css/style.css")) # 输出: https://www.example.com/css/style.css print(urljoin(base, "../about/")) # 输出: https://www.example.com/about/
解析: 会让路径返回上一级目录。urljoin 会正确地处理这种层级关系。
情况3:以 开头的绝对路径
这会覆盖掉 base_url 的路径部分。

from urllib.parse import urljoin base = "https://www.example.com/base/page.html" print(urljoin(base, "/about.html")) # 输出: https://www.example.com/about.html print(urljoin(base, "/api/v1/users")) # 输出: https://www.example.com/api/v1/users
解析:当相对 URL 以 开头时,它被认为是网站根目录下的绝对路径,base_url 的 /base/ 部分被完全替换。
情况4:完整的 URL(包含协议和域名)
relative_url 本身就是一个完整的绝对 URL,base_url 会被完全忽略。
from urllib.parse import urljoin base = "https://www.example.com/base/page.html" print(urljoin(base, "https://another-site.com/other-page")) # 输出: https://another-site.com/other-page print(urljoin(base, "ftp://files.example.com/data.zip")) # 输出: ftp://files.example.com/data.zip
解析:urljoin 会检查 relative_url 是否包含 scheme(如 http, https, ftp)或 netloc(域名),如果包含,就直接返回 relative_url 本身。
情况5:处理查询参数和片段
from urllib.parse import urljoin base = "https://www.example.com/base/page.html?user=123#section1" # 相对 URL 的查询参数会覆盖 base 的 print(urljoin(base, "?lang=en")) # 输出: https://www.example.com/base/page.html?lang=en # 相对 URL 的片段 会覆盖 base 的 print(urljoin(base, "#section2")) # 输出: https://www.example.com/base/page.html#section2 # 同时提供路径和查询参数 print(urljoin(base, "new.html?active=true")) # 输出: https://www.example.com/base/new.html?active=true
解析:查询参数(之后)和片段(之后)的处理逻辑是:relative_url 中有,则覆盖 base_url 中的对应部分。
为什么不直接用字符串拼接()?
这是一个非常关键的问题,直接使用字符串拼接很容易出错,尤其是在处理 的时候。
错误示范:
base_url = "https://www.example.com/base/page.html" relative_path = "../index.html" # 错误的拼接方式 wrong_url = base_url + relative_path print(wrong_url) # 输出: https://www.example.com/base/page.html../index.html (这是一个无效的URL!)
而 urljoin 能正确处理:
from urllib.parse import urljoin correct_url = urljoin(base_url, relative_path) print(correct_url) # 输出: https://www.example.com/index.html (这才是正确的!)
主要应用场景
-
网络爬虫: 当你解析一个网页时,会找到
<a href="...">,<img src="...">,<link href="...">等标签,它们的href或src属性通常是相对路径,你需要用urljoin将它们转换成完整的 URL 才能进行下一步的请求。 -
网站开发(后端): 在模板引擎(如 Jinja2)中,处理页面内的链接时,
urljoin可以确保链接始终指向正确的位置,无论当前页面的 URL 深度如何。 -
处理 API 响应: 某些 API 的响应中可能会返回一个
next_page字段,其值可能是一个相对 URL,在循环获取下一页数据时,需要用urljoin来构建完整的请求地址。
| 特性 | 描述 |
|---|---|
| 核心功能 | 智能拼接基础 URL 和相对 URL,生成绝对 URL。 |
| 智能之处 | 正确处理 、、完整的绝对 URL、查询参数和片段。 |
| 避免错误 | 防止因简单的字符串拼接()而产生的无效 URL。 |
| 必备工具 | 在任何需要处理网页链接的场景(爬虫、Web 开发)中,它都是一个不可或缺的工具。 |
urljoin 的黄金法则:用它来处理所有来自外部或不确定来源的 URL 片段,永远不要自己用字符串拼接来构造 URL,这能让你写出更健壮、更可靠的代码。
