Python 的 urljoin:告别手动拼接 URL 的烦恼

📌 前言

在日常爬虫、API 调用或 Web 开发中,我们经常需要拼接 URL。

比如基础地址是 https://example.com/api/,后面要加上 user/info,最终得到
https://example.com/api/user/info

很多新手会直接用 +f-string 来拼接,但这样很容易少写或多写斜杠,导致 URL 错误。

Python 标准库 urllib.parse 提供了一个非常方便的函数 ------ urljoin ,它能智能地拼接 URL,帮你自动处理斜杠问题。


🎯 作用一句话概括

urljoin(base, url) 将基础地址 base 和相对路径 url 拼接成一个完整、合法的绝对 URL。


📖 基本用法

复制代码
from urllib.parse import urljoin

base = "https://www.example.com"
relative = "login/"

full_url = urljoin(base, relative)
print(full_url)

输出:

复制代码
https://www.example.com/login/

瞧,它自动在 comlogin 之间加上了 /,完美!


🧪 几个简单的例子

✅ 例子 1:基础地址末尾有斜杠

复制代码
base = "https://example.com/"
relative = "api/user"
print(urljoin(base, relative))   # https://example.com/api/user

✅ 例子 2:基础地址末尾没有斜杠

复制代码
base = "https://example.com"
relative = "api/user"
print(urljoin(base, relative))   # https://example.com/api/user

注意:和例子 1 结果一样,urljoin 会自动补充斜杠,不用担心!

✅ 例子 3:相对路径以斜杠开头

复制代码
base = "https://example.com/abc/"
relative = "/login/"
print(urljoin(base, relative))   # https://example.com/login/

如果 relative/ 开头,它会替换掉整个路径部分,只保留协议和域名。

✅ 例子 4:相对路径是上一级目录

复制代码
base = "https://example.com/user/profile/"
relative = "../settings/"
print(urljoin(base, relative))   # https://example.com/user/settings/

urljoin 也支持 Unix 风格的相对路径 (...)。

✅ 例子 5:相对路径是一个完整的 URL

复制代码
base = "https://example.com"
relative = "https://google.com/search"
print(urljoin(base, relative))   # https://google.com/search

如果 relative 已经是一个完整的绝对 URL,urljoin直接返回它 ,忽略 base

✅ 例子 6:仅追加path

复制代码
base = "https://example.com/abc/"
relative = "login"

print(urljoin(base,relative)) # https://example.com/abc/login

可以封装成函数使用

复制代码
from urllib.parse import urljoin

def urljoin_test(base, relative):
    # rstrip('/'):去掉 base_url 末尾的斜杠,防止后面手动加 / 时出现双斜杠。
    base = base.rstrip('/')
    # base_url + '/':保证基础部分以 / 结尾。
    # path.lstrip('/'):去掉 path 开头的斜杠,保证中间只有一个 /。
    # 最后 urljoin 做最终的拼接,安全可靠。
    url = urljoin(base + '/', relative.lstrip('/'))
    return url

base = "https://example.com/abc/"
relative = "/login"

print(urljoin_test(base,relative))  # https://example.com/abc/login

如果把 relative 改成不以 / 开头,这时就会在原有路径后面追加 login/,而不是替换。


🚫 手动拼接有什么坑?

假设你想拼接 https://ex.com/api/v1/users

复制代码
# 错误示范 ❌
base = "https://ex.com/api"
bad_url = base + "/v1/users"   # 结果:https://ex.com/api/v1/users  (看起来对?)

好像没问题?但换个场景就出问题:

复制代码
base = "https://ex.com/api/"   # 末尾多了一个斜杠
bad_url = base + "/v1/users"   # 结果:https://ex.com/api//v1/users (两个斜杠!)

虽然浏览器有时能容忍双斜杠,但这不是规范的 URL,某些严格的服务端会报错。

urljoin 永远不会出现双斜杠:

复制代码
from urllib.parse import urljoin
base = "https://ex.com/api/"
print(urljoin(base, "/v1/users"))  # https://ex.com/api/v1/users ✅

💡 实际应用场景

场景 说明
爬虫 从 HTML 中提取 href="/news/123",与当前页面 URL 拼接成绝对链接
API 客户端 基础地址 https://api.example.com/v1,动态拼接 users, posts 等端点
Django/Flask 测试 测试中动态构建请求 URL
配置文件 配置一个 base_url,各处调用 urljoin 拼接子路径

📝 代码模板(直接复制用)

复制代码
from urllib.parse import urljoin

class ApiClient:
    def __init__(self, base_url):
        self.base_url = base_url.rstrip('/')  # 去掉末尾斜杠,urljoin 会自动加

    def _url(self, path):
        return urljoin(self.base_url + '/', path.lstrip('/'))

    def get_users(self):
        full_url = self._url("/users")
        print(f"请求地址: {full_url}")
        # 这里发请求...

client = ApiClient("https://myapi.com")
client.get_users()   # 输出: 请求地址: https://myapi.com/users

⚠️ 注意事项(新手常见疑问)

  1. urljoin 不会做网络请求,它只负责字符串拼接。

  2. 第二个参数以 // 开头 时(例如 //example.com/),会沿用原协议(http 或 https),但这种行为很多新手可能想不到,尽量避免这样用。

  3. 第二个参数以 ?# 开头时,会替换原 URL 的查询参数或锚点。

  4. 如果需要处理非常规 URL(比如 file:///C:/test),urljoin 也能工作。


🎓 总结

方法 是否智能处理斜杠 是否支持 .. 路径 推荐程度
手动 + 不推荐
f-string 不推荐
os.path.join ❌(用于文件路径,不是 URL) 不推荐
urljoin ✅ 强烈推荐

一句话记住:以后拼接 URL,直接用 urljoin,别再手动加斜杠了!


🔍 扩展阅读

相关推荐
南境十里·墨染春水2 小时前
C++笔记 STL——vector
开发语言·c++·笔记
智者知已应修善业2 小时前
【proteus78进制计数器与非门】2023-7-5
驱动开发·经验分享·笔记·硬件架构·硬件工程
思麟呀2 小时前
Epoll的学习,在select和poll的基础上
网络·数据库·sql·学习·tcp/ip
南境十里·墨染春水2 小时前
C++笔记 STL lterator迭代器
开发语言·c++·笔记
zjeweler2 小时前
宝藏网站推荐:云服务器特惠与网安学习资源的一站式聚合平台
运维·服务器·学习
芸开发3 小时前
VMware+RockyLinux10
linux·笔记
qq_571099353 小时前
学习周报四十二
学习
SunAqua3 小时前
《MCU与DSP芯片笔记》二、DSP芯片TI C2000系列TMS320F2800137
笔记·单片机·嵌入式硬件
HERR_QQ3 小时前
端到端课程自用 3 规划基于query的端到端规划
笔记·神经网络·学习·自动驾驶