前言
在网络数据采集场景中,路由跳转页面是高频出现的采集目标,此类页面通过前端路由、301/302 重定向、表单提交、异步跳转等方式实现页面切换,常规单页面爬虫无法完成连贯数据采集,极易出现数据缺失、采集中断、页面 404 等问题。本文聚焦路由跳转页面的连贯数据采集核心技术,从基础原理到高阶实战,覆盖同步重定向、前端 SPA 路由、异步跳转、嵌套跳转等全场景解决方案,结合完整可运行代码、原理剖析、性能优化与异常处理,帮助开发者实现稳定、高效、连贯的路由跳转页面数据采集。
本文使用的核心依赖库及官方文档链接如下:
- Requests:Python 最常用的 HTTP 请求库,支持自动重定向、会话保持
- BeautifulSoup4:HTML/XML 解析库,用于提取页面数据
- Selenium:浏览器自动化工具,适配前端动态路由跳转
- Urllib3:底层 HTTP 库,用于自定义重定向策略
- Playwright:现代化浏览器自动化工具,高性能适配 SPA 页面跳转
本文面向具备 Python 基础爬虫开发能力的开发者,所有代码均经过实测验证,可直接部署运行,覆盖企业级爬虫开发的路由跳转采集全需求。
一、路由跳转页面核心概念与分类
1.1 路由跳转定义
路由跳转是指网页在用户操作或程序触发下,从当前 URL 地址切换至另一个 URL 地址的过程,是现代 Web 应用的核心交互方式。爬虫场景中,路由跳转的核心难点在于保持采集会话的连贯性,确保跳转过程中的 Cookie、请求头、参数、登录状态不丢失,最终实现全链路数据采集。
1.2 路由跳转四大核心分类(爬虫适配视角)
表格
| 跳转类型 | 实现原理 | 典型特征 | 爬虫适配难点 |
|---|---|---|---|
| 服务端重定向(301/302) | 服务器返回重定向状态码,浏览器自动跳转 | 响应头包含 Location 字段,无前端渲染 | 自动重定向循环、跨域重定向会话丢失 |
| 前端 SPA 路由(Vue/React/Angular) | 前端 JavaScript 控制路由切换,无页面刷新 | URL 改变但页面不刷新,数据异步加载 | 静态爬虫无法捕获动态路由,数据加载延迟 |
| 表单提交跳转 | 表单数据提交后,服务器返回跳转页面 | POST 请求提交参数,跳转依赖表单验证 | 参数加密、Token 校验、重复提交限制 |
| 异步 Ajax 跳转 | 前端通过 Ajax 请求获取跳转地址,JS 执行跳转 | 无状态码跳转,跳转地址藏在响应数据中 | 跳转地址动态生成,无法通过常规重定向捕获 |
1.3 连贯数据采集核心要求
- 会话连续性:跳转全过程保持 Cookie、Session、Token 等身份信息不变
- 全链路追踪:记录每一次跳转的 URL、状态码、响应数据,避免数据丢失
- 异常容错:处理重定向循环、跳转失败、页面不存在等异常场景
- 高效采集:兼顾采集速度与稳定性,适配不同类型的路由跳转场景
二、前置环境配置与依赖安装
2.1 基础环境要求
- Python 版本:3.8 及以上(推荐 3.10+,兼容所有依赖库)
- 操作系统:Windows/Linux/MacOS 全平台兼容
- 浏览器环境:Selenium/Playwright 需安装对应浏览器驱动(下文提供安装方式)
2.2 核心依赖库安装命令
打开终端执行以下命令,一键安装所有必需库:
bash
运行
# 基础HTTP请求与解析库 pip install requests beautifulsoup4 lxml urllib3 # 浏览器自动化库 pip install selenium playwright # 安装Playwright浏览器驱动(必选,否则无法运行) playwright install2.3 依赖库核心作用说明
requests:处理 HTTP 请求,支持配置重定向策略、会话保持,是服务端重定向采集的核心工具beautifulsoup4:解析 HTML 页面,提取跳转链接、表单参数、目标数据selenium/playwright:模拟真实浏览器行为,处理前端 SPA 路由、异步跳转等动态场景urllib3:自定义重定向逻辑,解决 Requests 默认重定向无法处理的特殊场景
三、服务端重定向(301/302)页面连贯采集
服务端重定向是最基础的路由跳转类型,也是爬虫最常遇到的场景,Requests 库默认支持自动重定向,但高阶场景需要自定义策略实现连贯采集。
3.1 基础原理
服务器接收到请求后,返回 **301(永久重定向)或302(临时重定向)** 状态码,同时在响应头的Location字段中指定目标跳转地址,客户端(浏览器 / 爬虫)自动向新地址发起请求,完成跳转。
默认情况下,requests会自动处理最多 30 次重定向,超过则抛出异常,适用于简单场景,但无法满足自定义追踪、会话保持、异常处理的高阶需求。
3.2 基础自动重定向采集代码
python
运行
import requests # 基础请求:自动处理重定向 def basic_redirect_crawl(url: str): """ 基础服务端重定向采集 :param url: 初始跳转URL :return: 最终页面数据 """ # 禁用证书验证(适配部分https网站),设置超时时间 response = requests.get(url, verify=False, timeout=10) # 打印关键信息 print(f"初始URL:{url}") print(f"最终URL:{response.url}") print(f"响应状态码:{response.status_code}") print(f"重定向历史:{[hist.url for hist in response.history]}") # 返回页面文本数据 return response.text # 测试调用 if __name__ == '__main__': target_url = "https://www.baidu.com/link?url=xxx" # 示例重定向URL result = basic_redirect_crawl(target_url) print("最终页面内容长度:", len(result))代码原理剖析
requests.get()默认开启allow_redirects=True,自动处理 301/302 重定向response.history存储所有重定向历史记录,可追踪全链路跳转路径response.url获取跳转后的最终目标 URL,确保采集到正确页面verify=False关闭 SSL 证书验证,解决部分网站证书不兼容导致的请求失败
3.3 高阶自定义重定向采集(会话保持 + 跳转追踪)
企业级爬虫需要保持会话连贯、限制重定向次数、捕获每一次跳转数据,以下代码实现全功能适配:
python
运行
import requests from requests.exceptions import TooManyRedirects, Timeout def advanced_redirect_crawl(init_url: str, max_redirects: int = 5): """ 高阶服务端重定向连贯采集:会话保持、跳转追踪、异常处理 :param init_url: 初始URL :param max_redirects: 最大重定向次数 :return: 采集结果字典(跳转历史、响应数据、最终页面) """ # 创建会话对象:核心!保持Cookie、Header等会话信息连贯 session = requests.Session() # 配置请求头:模拟浏览器,避免被反爬拦截 session.headers.update({ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" }) # 存储跳转历史 redirect_history = [] final_response = None try: # 发送请求,自定义重定向次数 final_response = session.get( init_url, allow_redirects=True, max_redirects=max_redirects, timeout=15, verify=False ) # 记录所有跳转记录 redirect_history = [{"url": hist.url, "status_code": hist.status_code} for hist in final_response.history] # 添加最终页面到历史 redirect_history.append({"url": final_response.url, "status_code": final_response.status_code}) # 校验响应状态 final_response.raise_for_status() except TooManyRedirects: return {"status": "failed", "msg": f"重定向次数超过上限{max_redirects}", "history": redirect_history} except Timeout: return {"status": "failed", "msg": "请求超时", "history": redirect_history} except Exception as e: return {"status": "failed", "msg": f"请求异常:{str(e)}", "history": redirect_history} # 返回连贯采集结果 return { "status": "success", "init_url": init_url, "redirect_count": len(redirect_history) - 1, "redirect_history": redirect_history, "final_url": final_response.url, "final_content": final_response.text } # 测试调用 if __name__ == '__main__': result = advanced_redirect_crawl("https://www.baidu.com") print("跳转次数:", result["redirect_count"]) print("全链路跳转历史:", result["redirect_history"]) print("最终页面采集成功")代码原理剖析
requests.Session()核心作用:创建持久化会话对象,自动管理 Cookie、请求头、连接池,确保重定向全过程会话不中断,这是连贯数据采集的核心- 自定义请求头:模拟真实浏览器,绕过网站基础反爬机制
- 最大重定向限制:避免重定向循环导致程序卡死
- 全异常捕获:处理重定向超限、超时、网络错误等所有常见异常
- 结构化数据返回:记录跳转全链路信息,满足数据溯源需求
3.4 禁用自动重定向(手动控制跳转)
部分场景需要手动捕获重定向地址、修改跳转参数,可禁用自动重定向,实现手动连贯跳转:
python
运行
import requests def manual_redirect_crawl(init_url: str): """ 手动处理重定向:自定义跳转逻辑,适配特殊场景 """ session = requests.Session() current_url = init_url jump_count = 0 max_jump = 5 while jump_count < max_jump: # 禁用自动重定向 response = session.get(current_url, allow_redirects=False, verify=False, timeout=10) # 判断是否为重定向 if response.status_code in (301, 302, 303, 307, 308): # 从响应头获取跳转地址 next_url = response.headers.get("Location") # 处理相对路径跳转 if not next_url.startswith("http"): next_url = requests.compat.urljoin(current_url, next_url) jump_count += 1 print(f"第{jump_count}次跳转:{current_url} -> {next_url}") current_url = next_url else: # 非重定向,到达目标页面 break return {"final_url": current_url, "content": response.text, "jump_count": jump_count}代码原理剖析
allow_redirects=False:关闭自动重定向,手动处理跳转逻辑- 读取
Location响应头:获取真实跳转地址 - 相对路径补全:处理
/index这类相对地址,避免跳转失败 - 循环控制:手动实现多步跳转,灵活适配特殊业务场景
四、前端 SPA 路由页面连贯采集
SPA(单页应用)基于 Vue、React、Angular 等框架开发,路由跳转由前端 JavaScript 控制,无页面刷新、无服务端重定向状态码,常规静态爬虫无法捕获路由变化,是进阶爬虫的核心难点。
4.1 核心原理
SPA 应用将所有资源一次性加载到浏览器,通过history.pushState()或hash模式修改 URL,前端 JS 动态渲染页面数据,服务端无重定向响应。爬虫必须模拟浏览器执行 JS,才能追踪路由跳转并采集动态数据。
4.2 Playwright 实现 SPA 路由连贯采集(推荐)
Playwright 是现代化浏览器自动化工具,支持异步渲染、路由监听、自动等待,比 Selenium 更高效,是 SPA 页面采集的最优解:
python
运行
from playwright.sync_api import sync_playwright import time def spa_route_crawl(init_url: str, route_list: list): """ SPA前端路由连贯采集:监听路由变化,采集多页面数据 :param init_url: 初始页面URL :param route_list: 需要采集的路由路径列表(如 ["/home", "/list", "/detail"]) :return: 各路由页面数据字典 """ result = {} with sync_playwright() as p: # 启动无头浏览器(无界面,提升性能) browser = p.chromium.launch(headless=True) # 创建浏览器上下文:保持会话连贯 context = browser.new_context( user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" ) page = context.new_page() # 访问初始页面,等待页面加载完成 page.goto(init_url, timeout=30000) page.wait_for_load_state("networkidle") # 等待网络空闲,确保JS渲染完成 result["init_page"] = page.content() print("初始页面采集完成") # 遍历目标路由,实现连贯跳转采集 for route in route_list: try: # 拼接完整路由地址 full_url = init_url.rstrip("/") + route # 路由跳转 page.goto(full_url) # 等待动态数据加载(关键:等待指定元素出现,避免数据未渲染完成) page.wait_for_selector("body", timeout=10000) time.sleep(1) # 额外等待,适配慢响应页面 # 采集当前路由页面数据 page_content = page.content() result[route] = page_content print(f"路由{route}采集成功,数据长度:{len(page_content)}") except Exception as e: result[route] = f"采集失败:{str(e)}" print(f"路由{route}采集异常:{str(e)}") # 关闭资源 page.close() context.close() browser.close() return result # 测试调用 if __name__ == '__main__': # 示例:Vue/React SPA网站 target_init_url = "https://spa-demo.example.com" target_routes = ["/home", "/product/list", "/about"] crawl_result = spa_route_crawl(target_init_url, target_routes)代码原理剖析
- 无头浏览器启动:
headless=True无界面运行,降低资源消耗,提升采集速度 - 浏览器上下文:
new_context()保持会话连贯,Cookie、LocalStorage 跨路由共享 wait_for_load_state("networkidle"):等待网络请求完成,确保 SPA 页面完全渲染wait_for_selector():等待页面元素加载,解决 JS 异步渲染延迟问题- 多路由遍历:实现 SPA 应用内多页面连贯采集,无会话丢失
4.3 Selenium 实现 SPA 路由采集(兼容老旧框架)
Selenium 是传统浏览器自动化工具,兼容性更强,适配老旧 SPA 框架:
python
运行
from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def selenium_spa_crawl(init_url: str): """ Selenium实现SPA路由连贯采集 """ # 配置Chrome选项 chrome_options = Options() chrome_options.add_argument("--headless=new") # 无头模式 chrome_options.add_argument("--disable-gpu") chrome_options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36") # 启动浏览器 driver = webdriver.Chrome(options=chrome_options) driver.get(init_url) # 等待页面加载 WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.TAG_NAME, "body"))) # 采集初始页面 result = {"init_page": driver.page_source} # 模拟前端路由跳转(示例:点击按钮跳转路由) try: # 定位跳转按钮 jump_btn = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CLASS_NAME, "route-btn")) ) jump_btn.click() # 等待跳转后页面加载 time.sleep(2) # 采集跳转后页面 result["spa_jump_page"] = driver.page_source print("SPA路由跳转采集成功") except Exception as e: result["spa_jump_page"] = f"失败:{str(e)}" driver.quit() return result代码原理剖析
- Chrome 配置:无头模式、禁用 GPU,适配服务器无界面环境
- 显示等待:
WebDriverWait替代强制等待,提升采集效率 - 模拟用户操作:通过点击按钮触发前端路由跳转,完全还原真实用户行为
page_source:获取 JS 渲染后的完整 HTML,实现动态数据采集
五、表单提交跳转页面连贯采集
表单提交跳转是常见的业务场景(登录、搜索、查询等),通过 POST 请求提交参数后,服务器返回跳转页面,采集核心是正确提交参数 + 保持会话连贯。
5.1 核心原理
前端通过<form>表单收集用户数据,以 POST/GET 方式提交至服务端,服务端验证参数后返回重定向响应或直接渲染目标页面,爬虫需要模拟表单提交,携带完整参数与会话信息。
5.2 完整表单跳转采集代码
python
运行
import requests from bs4 import BeautifulSoup def form_redirect_crawl(form_page_url: str, submit_url: str, form_data: dict): """ 表单提交跳转页面连贯采集 :param form_page_url: 表单页面URL :param submit_url: 表单提交地址 :param form_data: 表单提交参数 :return: 跳转后页面数据 """ session = requests.Session() # 1. 访问表单页面,获取隐藏参数(如csrf_token、验证码等) form_page = session.get(form_page_url, verify=False, timeout=10) soup = BeautifulSoup(form_page.text, "lxml") # 提取表单隐藏参数(反爬必备,示例:提取csrf_token) try: csrf_token = soup.find("input", attrs={"name": "csrf_token"})["value"] form_data["csrf_token"] = csrf_token print("成功提取隐藏CSRF Token") except: print("无隐藏参数,直接提交") # 2. 提交表单,触发跳转 response = session.post( submit_url, data=form_data, allow_redirects=True, timeout=15 ) # 3. 返回跳转后页面数据 return { "status": "success" if response.status_code == 200 else "failed", "final_url": response.url, "content": response.text, "redirect_history": [hist.url for hist in response.history] } # 测试调用 if __name__ == '__main__': # 示例:搜索表单提交跳转 form_page = "https://search.example.com" submit_page = "https://search.example.com/api/search" data = {"keyword": "python爬虫", "page": 1} result = form_redirect_crawl(form_page, submit_page, data) print("表单跳转后最终URL:", result["final_url"])代码原理剖析
- 两步采集:先访问表单页面获取隐藏反爬参数,再提交表单,绕过网站参数校验
- 会话保持:
Session对象确保表单页面与提交请求的 Cookie 一致,通过服务端验证 - 自动重定向:提交表单后自动处理跳转,直达目标数据页面
- 隐藏参数提取:解决表单提交必备的 Token、验证码等反爬机制
六、异步 Ajax 跳转页面连贯采集
异步 Ajax 跳转是现代网站常用技术,跳转地址不通过响应头返回,而是藏在 Ajax 响应的 JSON/HTML 数据中,由 JS 动态执行跳转,常规爬虫无法捕获。
6.1 核心原理
前端通过 Ajax/fetch 请求接口,服务端返回包含跳转 URL 的数据,前端 JS 解析数据后执行window.location.href=url实现跳转,爬虫需要解析 Ajax 响应数据,提取跳转地址,再发起请求。
6.2 Ajax 跳转采集完整代码
python
运行
import requests import json def ajax_redirect_crawl(ajax_api_url: str, headers: dict): """ 异步Ajax跳转页面连贯采集 :param ajax_api_url: Ajax请求接口地址 :param headers: 请求头(包含必要的Token、Cookie) :return: 跳转后页面数据 """ session = requests.Session() session.headers.update(headers) # 1. 发送Ajax请求,获取跳转地址 ajax_response = session.get(ajax_api_url, verify=False, timeout=10) if ajax_response.status_code != 200: return {"status": "failed", "msg": "Ajax请求失败"} # 2. 解析响应数据,提取跳转地址 try: # 解析JSON格式数据(适配绝大多数Ajax接口) ajax_data = json.loads(ajax_response.text) jump_url = ajax_data.get("data", {}).get("jumpUrl") if not jump_url: return {"status": "failed", "msg": "未找到跳转地址"} print(f"提取Ajax跳转地址:{jump_url}") except: # 适配HTML格式响应 jump_url = ajax_response.text.strip() if not jump_url.startswith("http"): jump_url = requests.compat.urljoin(ajax_api_url, jump_url) # 3. 访问跳转地址,完成连贯采集 final_response = session.get(jump_url, verify=False, timeout=10) return { "status": "success", "ajax_url": ajax_api_url, "jump_url": jump_url, "final_content": final_response.text } # 测试调用 if __name__ == '__main__': ajax_url = "https://api.example.com/getJumpUrl" req_headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Content-Type": "application/json" } result = ajax_redirect_crawl(ajax_url, req_headers) print("Ajax跳转页面采集完成")代码原理剖析
- Ajax 接口请求:直接请求数据接口,而非页面,获取真实跳转地址
- 多格式解析:兼容 JSON/HTML 两种响应格式,覆盖主流 Ajax 跳转场景
- 地址补全:处理相对路径跳转地址,避免请求失败
- 连贯会话:使用同一个 Session 对象,确保 Ajax 请求与跳转页面请求的身份信息一致
七、嵌套路由跳转全场景连贯采集方案
实际业务场景中,路由跳转往往是多种类型嵌套(如:302 重定向→SPA 路由→Ajax 跳转→表单跳转),需要整合所有技术,实现全场景连贯采集。
7.1 通用嵌套跳转采集框架
python
运行
import requests from playwright.sync_api import sync_playwright class UniversalRedirectCrawler: """ 全场景路由跳转连贯采集框架:适配所有跳转类型 """ def __init__(self, user_agent=None): # 初始化会话与配置 self.session = requests.Session() self.default_headers = { "User-Agent": user_agent or "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" } self.session.headers.update(self.default_headers) self.max_jump = 10 def crawl(self, init_url): """ 全场景采集入口 """ current_url = init_url jump_history = [] content = None for _ in range(self.max_jump): # 第一步:尝试静态请求处理服务端重定向 response = self.session.get(current_url, allow_redirects=False, verify=False, timeout=15) jump_history.append({"url": current_url, "status": response.status_code}) # 判断:服务端重定向 if response.status_code in (301, 302, 307, 308): current_url = self._get_full_url(response.headers.get("Location"), current_url) continue # 判断:SPA/异步跳转(启用浏览器采集) if self._is_spa_page(response.text): content = self._crawl_spa_page(current_url) break # 静态页面:直接返回数据 content = response.text break return { "init_url": init_url, "jump_history": jump_history, "final_content": content, "jump_count": len(jump_history) - 1 } def _get_full_url(self, url, base_url): """补全跳转地址""" return url if url.startswith("http") else requests.compat.urljoin(base_url, url) def _is_spa_page(self, html): """判断是否为SPA页面(关键词检测)""" spa_keywords = ["vue", "react", "angular", "spa", "pushState"] return any(keyword in html.lower() for keyword in spa_keywords) def _crawl_spa_page(self, url): """浏览器渲染采集SPA页面""" with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto(url) page.wait_for_load_state("networkidle") content = page.content() browser.close() return content # 测试调用 if __name__ == '__main__': crawler = UniversalRedirectCrawler() result = crawler.crawl("https://www.example.com") print(f"嵌套跳转采集完成,共跳转{result['jump_count']}次")7.2 方案核心优势
- 全场景适配:自动识别跳转类型,无需手动配置
- 连贯采集:统一会话管理,无身份信息丢失
- 高性能:静态请求优先,仅必要时启用浏览器渲染
- 高容错:最大跳转次数限制,异常自动终止,避免程序卡死
八、路由跳转爬虫性能优化与反爬规避
8.1 性能优化技巧
表格
| 优化方向 | 具体方案 | 效果 |
|---|---|---|
| 连接复用 | 使用requests.Session()连接池,减少 TCP 握手开销 | 采集速度提升 30% 以上 |
| 无头模式 | 浏览器采集启用无头模式,禁用图片 / CSS 加载 | 降低内存占用 50% |
| 智能等待 | 使用显示等待替代强制等待 | 减少无效等待时间,提升效率 |
| 并发控制 | 限制同时请求数量,避免目标服务器限流 | 保证采集稳定性 |
8.2 反爬规避核心策略
- 请求头合规:必须携带
User-Agent、Referer、Origin等请求头 - 频率控制:跳转间隔设置 1-3 秒延迟,避免高频请求被封禁
- Cookie 持久化:保存会话 Cookie,避免重复登录 / 验证
- 随机化行为:随机切换 User-Agent、请求间隔,模拟真实用户
- 代理 IP:大规模采集使用代理 IP,规避 IP 封禁
九、异常处理与故障排查
9.1 常见异常及解决方案
表格
| 异常类型 | 触发原因 | 解决方案 |
|---|---|---|
| 重定向循环 | 服务器配置错误,跳转地址互相指向 | 限制最大重定向次数,手动终止 |
| 403 Forbidden | 反爬拦截,请求头 / IP 异常 | 补充请求头,使用代理 IP |
| 404 Not Found | 跳转地址失效,相对路径未补全 | 校验跳转地址格式,补全绝对路径 |
| JS 渲染失败 | 静态爬虫采集 SPA 页面 | 启用 Playwright/Selenium 浏览器渲染 |
| 会话丢失 | 未使用 Session 对象,跨请求 Cookie 不共享 | 统一使用 requests.Session 管理会话 |
9.2 故障排查步骤
- 打印跳转历史,确认每一步跳转地址与状态码
- 检查请求头是否完整,是否模拟真实浏览器
- 验证跳转地址是否为绝对路径,避免相对路径错误
- 动态页面启用浏览器渲染,确保 JS 执行完成
- 检查网络连接与目标网站可用性,排除网络故障
十、企业级实战案例:电商平台路由跳转商品采集
10.1 业务场景
某电商平台商品列表页→商品详情页采用302 重定向 + SPA 路由嵌套跳转,需要连贯采集商品列表与详情数据。
10.2 完整实战代码
python
运行
# 企业级电商路由跳转商品采集实战 import requests from bs4 import BeautifulSoup from playwright.sync_api import sync_playwright class EcommerceCrawler: def __init__(self): self.session = requests.Session() self.session.headers.update({ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" }) self.base_url = "https://www.ecommerce-demo.com" def get_product_list(self): """采集商品列表(302重定向页面)""" list_url = f"{self.base_url}/product/list" response = self.session.get(list_url, verify=False, timeout=15) soup = BeautifulSoup(response.text, "lxml") # 提取商品详情页跳转链接 product_items = soup.find_all("div", class_="product-item") product_links = [item.find("a")["href"] for item in product_items] print(f"成功获取{len(product_links)}个商品链接") return product_links def crawl_product_detail(self, detail_url): """采集商品详情页(SPA路由页面)""" with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto(detail_url) page.wait_for_load_state("networkidle") # 提取商品数据 product_name = page.query_selector(".product-name").inner_text() product_price = page.query_selector(".product-price").inner_text() browser.close() return {"name": product_name, "price": product_price, "url": detail_url} def run(self): """全流程连贯采集""" print("开始电商平台商品采集...") # 1. 获取商品列表(302重定向) product_links = self.get_product_list() # 2. 连贯采集商品详情(SPA路由) result = [] for link in product_links[:3]: # 限制采集数量,测试用 full_link = link if link.startswith("http") else f"{self.base_url}{link}" detail = self.crawl_product_detail(full_link) result.append(detail) print(f"采集商品:{detail['name']} - {detail['price']}") return result if __name__ == '__main__': crawler = EcommerceCrawler() final_result = crawler.run() print("所有商品采集完成:", final_result)