Python如何正确解析处理相对URL与完整URL?
Python 正确解析HTML页面多形式链接的实现方案
手动拼接URL的方案存在两类核心问题:
- 未覆盖所有链接引用形式:非
/开头的链接直接输出原始请求地址,完全缺失目录相对路径的拼接逻辑 - 未适配重定向场景:直接用初始请求URL作为拼接基准,没有考虑重定向后落地地址变化的情况,也没有处理URL携带查询参数、锚点对路径拼接的影响
不要自行实现URL字符串拼接逻辑,Python标准库urllib.parse提供的urljoin方法已经完整覆盖W3C规定的所有URL解析规则,配合requests响应对象获取重定向后的真实地址,即可覆盖所有需求场景。
具体实现步骤
- 发起请求后,从响应对象中获取重定向后的最终访问地址,而非使用初始传入的请求URL
- 对最终地址做清洗:移除查询参数、锚点,将非目录结尾的路径处理为标准目录格式,作为URL拼接的基准地址
- 遍历提取到的所有页面链接,用
urljoin自动完成链接解析,无需手动判断链接类型
可直接运行的示例代码
import requests from urllib.parse import urljoin, urlparse, urlunparse def get_parse_base_url(response): # 获取重定向后的最终落地URL final_visit_url = response.url parsed_url = urlparse(final_visit_url) # 清洗路径:如果路径不是/结尾,说明是具体页面/文件,取其所在目录作为基准 path = parsed_url.path if not path.endswith("/"): path = path.rsplit("/", 1)[0] + "/" # 移除参数、查询串、锚点,拼接成标准基准URL base_config = parsed_url._replace( path=path, params="", query="", fragment="" ) return urlunparse(base_config) if __name__ == "__main__": # 替换为实际要访问的初始地址 init_url = "https://example.com" resp = requests.get(init_url) base_url = get_parse_base_url(resp) # 替换为从HTML中实际提取到的链接列表 extract_links = [ "https://example.com/images/picture.jpg", "/images/picture.jpg", "images/picture.jpg" ] for link in extract_links: # 自动适配三种链接形式,输出正确的完整地址 print(urljoin(base_url, link))
场景验证
以给定的解析规则做验证:
- 完整URL形式的链接:
urljoin会直接返回原链接地址,不会重复拼接 - 根路径相对形式(
/开头)的链接:会自动匹配基准URL的域名部分,拼接出正确的域名+路径地址 - 目录相对形式(非
/开头、非完整URL)的链接:会基于基准URL的目录路径完成拼接 - 重定向场景:比如初始访问
https://example.com被重定向到https://example.com/homepage?ignore=yes,函数会自动清洗得到基准地址https://example.com/homepage/,后续相对路径拼接完全符合预期。
额外说明:标准库
urljoin还自动兼容协议相对路径(//example.com/xxx)、路径回退(../xxx.jpg)等更多特殊URL形式,比手动拼接的鲁棒性高很多,不需要额外写判断逻辑覆盖。
内容的提问来源于stack exchange,提问作者tom
相关产品推荐
相关产品推荐

