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/瞧它自动在com和login之间加上了/完美 几个简单的例子✅ 例子 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相对路径是一个完整的 URLbase https://example.com relative https://google.com/search print(urljoin(base, relative)) # https://google.com/search如果relative已经是一个完整的绝对 URLurljoin会直接返回它忽略base。✅ 例子 6仅追加pathbase 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⚠️ 注意事项新手常见疑问urljoin不会做网络请求它只负责字符串拼接。第二个参数以//开头时例如//example.com/会沿用原协议http 或 https但这种行为很多新手可能想不到尽量避免这样用。第二个参数以?或#开头时会替换原 URL 的查询参数或锚点。如果需要处理非常规 URL比如file:///C:/testurljoin也能工作。 总结方法是否智能处理斜杠是否支持..路径推荐程度手动❌❌不推荐f-string❌❌不推荐os.path.join❌用于文件路径不是 URL❌不推荐urljoin✅✅✅ 强烈推荐一句话记住以后拼接 URL直接用urljoin别再手动加斜杠了 扩展阅读官方文档urllib.parse.urljoinRFC 1808 - Relative Uniform Resource Locators