如何用Python Requests获取非3XX场景下的更新跳转URL?
如何用Python获取浏览器中显示的最终URL(非HTTP 3XX跳转场景)
问题背景
有三个原始URL:
raw_urls = [ 'https://digi.kansalliskirjasto.fi/aikakausi/binding/498491?term=1864&term=SUOMI&language=fi', 'https://twitter.com/i/user/2274951674', 'https://youtu.be/dQw4w9WgXcQ' ]
使用Requests库的HEAD或GET方法(开启自动重定向)时,仅能正确处理第三个URL(返回HTTP 3XX重定向),前两个URL无法获取到浏览器中显示的最终地址:
- 预期最终URL:
https://digi.kansalliskirjasto.fi/aikakausi/binding/498491?term=1864&term=SUOMI&page=1 https://twitter.com/ozanbayram01 https://www.youtube.com/watch?v=dQw4w9WgXcQ
问题原因
前两个URL的跳转并非HTTP 3XX重定向,而是:
- 前端通过JavaScript触发的路由跳转(如Twitter的用户ID转用户名)
- 服务器端渲染页面但未返回3XX状态码,而是在页面内容中隐含跳转逻辑(如图书馆网站的参数替换)
Requests库仅能处理HTTP协议层面的重定向,无法解析JS或页面内的跳转逻辑,因此无法获取最终URL。
解决方法
1. 使用模拟浏览器的工具(最可靠)
使用Playwright、Pyppeteer等工具模拟真实浏览器行为,它们会执行页面中的JavaScript,完全复现浏览器的跳转流程。
示例代码(Playwright)
from playwright.sync_api import sync_playwright def get_browser_final_url(raw_url): with sync_playwright() as p: # 启动无头浏览器(不显示界面) browser = p.chromium.launch(headless=True) page = browser.new_page() # 等待页面加载完成(网络空闲状态) page.goto(raw_url, wait_until="networkidle") final_url = page.url browser.close() return final_url # 测试所有URL raw_urls = [ 'https://digi.kansalliskirjasto.fi/aikakausi/binding/498491?term=1864&term=SUOMI&language=fi', 'https://twitter.com/i/user/2274951674', 'https://youtu.be/dQw4w9WgXcQ' ] for url in raw_urls: print(f"原始URL: {url}") print(f"最终URL: {get_browser_final_url(url)}\n")
2. 针对特定网站优化Requests请求(轻量方案)
部分网站可以通过模拟浏览器请求头、解析页面内容来获取最终URL,无需依赖浏览器工具。
示例代码(Requests+页面解析)
import requests from bs4 import BeautifulSoup # 模拟浏览器请求头 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' } def get_final_url_with_requests(raw_url): response = requests.get(raw_url, headers=headers, allow_redirects=True) response.raise_for_status() # 先检查HTTP重定向后的URL final_url = response.url # 针对Twitter用户ID页面,解析页面的canonical链接 if 'twitter.com/i/user' in raw_url: soup = BeautifulSoup(response.text, 'html.parser') canonical_link = soup.find('link', rel='canonical') if canonical_link: final_url = canonical_link['href'] # 针对芬兰图书馆网站,替换参数(根据浏览器观察到的规则) if 'digi.kansalliskirjasto.fi' in raw_url: final_url = final_url.replace('&language=fi', '&page=1') return final_url # 测试 for url in raw_urls: print(f"原始URL: {url}") print(f"最终URL: {get_final_url_with_requests(url)}\n")
方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| 模拟浏览器工具 | 适配所有跳转场景,最可靠 | 需安装浏览器,资源占用高 |
| Requests+页面解析 | 轻量,运行速度快 | 依赖网站实现,易失效 |
内容的提问来源于stack exchange,提问作者farid
相关产品推荐
相关产品推荐

