You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scrapy中如何让urljoin拼接URL时保留基础路径完整层级

问题根因

urllib.parse.urljoin 本身的设计逻辑是:base URL 末尾如果没有斜杠,最后一段路径会被识别为文件名,拼接时会直接替换该文件名;如果末尾带斜杠,最后一段会被识别为目录,扩展路径会拼接到目录下。你遇到的拼接不符合预期的问题就是这个逻辑导致的。

规范实现方案

不需要手动拆分拼接字符串,下面两种方案都是基于原生工具逻辑实现,比手动拼接的兼容性、稳定性更高,能覆盖绝对路径、相对跳转、带参数URL等各种边界场景:

方案1:统一补全base URL末尾斜杠

先对base URL做标准化处理,确保末尾带斜杠后再调用urljoin即可:

from urllib.parse import urljoin

def custom_urljoin(base_url: str, extension: str) -> str:
    # 先移除末尾所有斜杠,再加一个,避免重复斜杠
    processed_base = base_url.rstrip('/') + '/'
    return urljoin(processed_base, extension)

效果测试

# 单层路径场景
>>> custom_urljoin('https://url/part1', 'extension')
'https://url/part1/extension'

# 多层路径场景
>>> custom_urljoin('https://url/part1/part2', 'extension')
'https://url/part1/part2/extension'

# 扩展路径带相对跳转场景,手动拼接无法正确处理
>>> custom_urljoin('https://url/part1/part2', '../other')
'https://url/part1/other'

# 扩展路径为绝对路径时,自动返回绝对路径符合通用URL规范
>>> custom_urljoin('https://url/part1', 'https://other-domain.com/path')
'https://other-domain.com/path'

方案2:给扩展路径加./前缀

如果不想封装函数,也可以直接在扩展路径前加./(表示当前目录),不需要修改base URL就能达到相同效果:

>>> urljoin('https://url/part1', './extension')
'https://url/part1/extension'
>>> urljoin('https://url/part1/part2', './extension')
'https://url/part1/part2/extension'

Scrapy 场景适配

在Scrapy中使用response.urljoin时,直接套用上面两种方案即可:

# 方案1写法
processed_base = response.url.rstrip('/') + '/'
full_url = urljoin(processed_base, extension)

# 方案2更简洁的写法
full_url = response.urljoin(f'./{extension}')

内容的提问来源于stack exchange,提问作者watch-this

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 20:21:02