如何使用Scrapy框架等待页面完全加载以爬取目标数据?
解决办法
你碰到的问题核心是:页面里的目标数据是JavaScript动态渲染出来的,Scrapy默认抓取的是服务器返回的初始HTML,而你在浏览器审查元素看到的是渲染后的DOM结构,所以初始HTML里根本没有那个XPath对应的元素。
当然可以通过等待页面加载来提取数据,但得配合能处理JS渲染的工具,给你两种实用方案:
方案1:用Playwright配合Scrapy模拟浏览器加载
Playwright能模拟浏览器完整加载页面,等JS执行完毕后再抓取DOM,步骤如下:
- 先安装依赖:
pip install scrapy-playwright - 在Scrapy的
settings.py中添加配置:DOWNLOAD_HANDLERS = { "http": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler", "https": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler", } SPIDER_MIDDLEWARES = { "scrapy_playwright.middleware.PlaywrightMiddleware": 543, } - 在爬虫代码中设置等待元素加载:
def start_requests(self): yield scrapy.Request( url="https://openweathermap.org/city/625665", meta={"playwright": True, "playwright_include_page": True}, callback=self.parse, ) async def parse(self, response): page = response.meta["playwright_page"] # 等待目标元素加载完成 await page.wait_for_selector('//*[@id="weather-widget"]/div[2]/div[1]/div[1]/div[1]/h2') # 获取渲染后的页面内容 rendered_html = await page.content() selector = scrapy.Selector(text=rendered_html) target_data = selector.xpath('//*[@id="weather-widget"]/div[2]/div[1]/div[1]/div[1]/h2/text()').get() print(target_data) await page.close()
方案2:直接爬取后台API(更高效)
打开浏览器开发者工具的「网络」标签,刷新页面后筛选XHR类型的请求,你会发现天气数据其实是通过API接口返回的JSON。直接请求这个API比模拟浏览器加载快得多,还能避免JS渲染的麻烦——找到类似/data/2.5/weather的接口,带上城市ID参数就能拿到结构化数据。
内容的提问来源于stack exchange,提问作者Zakhar Malinouski
相关产品推荐
相关产品推荐

