Scrapy爬取疑问:HTTP GET响应JSON元素多于浏览器显示,如何获取过滤后数组?
解决Scrapy获取浏览器过滤后JSON数据的问题
嘿,这个场景我刚入门爬取的时候也踩过坑!浏览器显示的条目比API返回的少,核心原因几乎都是前端在拿到完整JSON后做了客户端过滤/截取,咱们一步步拆解解决:
第一步:搞清楚前端的过滤逻辑
首先得弄明白浏览器是怎么从140+条里筛出90条的,这一步靠浏览器开发者工具就能搞定:
- 按下
F12打开开发者工具,切换到「Network」标签,找到那个返回JSON的GET请求,查看「Response」面板确认完整的140+条数据确实返回了。 - 切换到「Elements」标签,找到页面上显示数据的DOM容器,记住它的类名或ID。
- 再切到「Sources」标签,搜索和数据处理相关的关键词(比如
filter、slice、display、你找到的DOM容器类名),找到前端处理数据的代码段。举个常见的例子:你可能会看到类似
const showItems = allData.filter(item => item.isVisible === true && item.date > '2024-01-01')的代码,这就明确了过滤条件是isVisible为真且日期在2024年之后。
第二步:在Scrapy里复刻过滤逻辑
当你搞清楚前端的过滤规则后,直接在Scrapy的parse方法里实现相同的判断就行,不用再去纠结浏览器的显示:
import json from scrapy.spiders import Spider class MySpider(Spider): name = 'my_spider' start_urls = ['https://example.com/api/data'] # 替换成你的目标API地址 def parse(self, response): # 解析完整的JSON响应 full_data = json.loads(response.text) # 复刻前端的过滤条件,这里替换成你找到的规则 filtered_data = [ item for item in full_data if item.get('isVisible') is True and item.get('date', '') > '2024-01-01' ] # 处理过滤后的每条数据 for item in filtered_data: yield { 'id': item.get('id'), 'title': item.get('title'), 'content': item.get('content') # 其他你需要的字段 }
第三步:复杂场景的替代方案
如果前端的过滤逻辑特别复杂(比如涉及加密参数、动态计算的判断条件),复刻规则太麻烦,那可以用Scrapy结合浏览器渲染工具直接获取页面上已显示的数据:
- 用
scrapy-playwright或者scrapy-splash集成浏览器渲染,让爬虫模拟真实浏览器加载页面,然后直接从渲染后的DOM里提取显示的条目,这样就完全不用管前端的过滤逻辑了。 - 举个
scrapy-playwright的简单示例,在settings.py里配置好后,在爬虫里直接获取页面元素:
def parse(self, response): # 直接提取页面上显示的条目DOM for item_elem in response.css('.display-item-class'): # 替换成你找到的DOM类名 yield { 'title': item_elem.css('.title::text').get(), 'content': item_elem.css('.content::text').get() }
额外提醒
如果发现滚动页面后浏览器会加载更多数据,那可能是前端做了滚动加载,但你说的是API返回140+条却只显示90,这种情况概率较低,但也可以检查下Network里有没有后续的请求,确认是不是分页加载的问题。
内容的提问来源于stack exchange,提问作者hsy




