如何使用Scrapy获取HTML源码中未显示的页面数据?
解决Scrapy爬取始祖鸟页面商品数据的问题
问题核心分析
页面源码中无商品数据,是因为该页面采用客户端渲染(CSR):初始HTML仅包含页面框架,商品数据由浏览器加载JavaScript后,通过AJAX请求后端接口获取并动态渲染到页面上。懒加载可能是附加场景(滚动加载更多商品),但初始商品列表同样是通过接口异步加载的,这才是你用CSS选择器无法获取数据的根本原因。
解决方案
1. 直接爬取后端API接口(推荐)
这是最高效、稳定的方式,无需处理JS渲染:
- 打开浏览器开发者工具(F12),切换到
Network标签,刷新目标页面; - 筛选
XHR/Fetch类型的请求,查找包含product、list、catalog等关键词的接口(比如始祖鸟的商品列表接口通常是/api/v1/catalog/products这类格式); - 查看请求的URL、请求头(尤其是
Authorization、Cookie等可能的验证字段)和返回的JSON数据,里面会包含完整的商品信息(ID、名称、价格、详情链接、图片等); - 在Scrapy中直接请求该API接口,解析JSON响应:
import scrapy class ArcteryxSpider(scrapy.Spider): name = "arcteryx" start_urls = ["https://arcteryx.com/de/de/api/v1/catalog/products?category=mens-new-arrivals&..."] # 替换为实际API地址 def parse(self, response): data = response.json() for product in data.get("products", []): yield { "id": product.get("id"), "name": product.get("name"), "price": product.get("price"), "detail_url": f"https://arcteryx.com/de/de/p/{product.get('slug')}" # 提取其他所需字段 }
2. 使用JS渲染工具(如Scrapy-Playwright)
如果API接口有签名验证、反爬机制难以绕过,可以用浏览器渲染页面,获取JS执行后的完整HTML:
- 安装依赖:
pip install scrapy-playwright - 在Scrapy项目的
settings.py中配置:DOWNLOAD_HANDLERS = { "http": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler", "https": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler", } PLAYWRIGHT_LAUNCH_OPTIONS = {"headless": True} # 无头模式,如需可视化调试设为False - 编写爬虫代码,启用Playwright渲染:
import scrapy class ArcteryxSpider(scrapy.Spider): name = "arcteryx" start_urls = ["https://arcteryx.com/de/de/c/mens/new-arrivals?intcmp=home_t1_c_mens_new-arrivals"] def start_requests(self): for url in self.start_urls: yield scrapy.Request(url, meta={"playwright": True}, callback=self.parse) def parse(self, response): # 此时response已包含JS渲染后的HTML products = response.css('div[class^="LazyProductTile__Wrap"]') for product in products: yield { "name": product.css("h3::text").get().strip(), "price": product.css("span[class*='Price']::text").get().strip(), "detail_url": product.css("a::attr(href)").get() }
3. 处理懒加载场景
如果页面需要滚动到底部才加载更多商品,可通过Playwright模拟滚动:
async def parse(self, response): page = response.meta["playwright_page"] # 多次滚动+等待,确保加载所有商品 for _ in range(3): await page.evaluate("window.scrollTo(0, document.body.scrollHeight)") await page.wait_for_timeout(2000) # 等待2秒让新内容加载 # 重新获取渲染后的HTML rendered_content = await page.content() selector = scrapy.Selector(text=rendered_content) products = selector.css('div[class^="LazyProductTile__Wrap"]') # 后续商品提取逻辑同前
内容的提问来源于stack exchange,提问作者Vaidas
相关产品推荐
相关产品推荐

