Scrapy框架如何检测并爬取带无限滚动机制的网页
无限滚动页面爬取方案
Scrapy默认仅发起初始HTTP请求、不执行页面JS,而无限滚动的实现逻辑是:用户滚动到页面底部时,前端自动发起异步请求拉取下一批内容追加到当前页,因此初始请求拿到的HTML仅包含首屏数据,自然会出现数据不全的问题。
优先用接口直连方案(效率最高,不依赖浏览器渲染)
1. 定位动态加载接口
不要上来就接Selenium/Playwright这类重渲染工具,先按以下步骤抓接口,效率比重方案高几十倍:
- 打开目标页面,按F12调出开发者工具,切换到「网络」面板,勾选
Fetch/XHR过滤规则 - 清空现有请求记录,手动滚动页面到底部触发新内容加载
- 观察新增的请求,这类接口一般带
page、offset、cursor、start这类分页参数,返回结果要么是结构化JSON,要么是待插入页面的HTML片段 - 手动修改分页参数发起请求,验证是否能直接拿到对应页内容,不需要额外签名、cookie校验的话,直接在Scrapy里构造请求爬取即可。
2. 改造现有爬虫代码
原有CrawlSpider的规则不需要全部推翻,只需要针对存在无限滚动的页面单独加分页递推逻辑即可,参考改法:
import re from scrapy import Request from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from w3lib.url import url_query_cleaner, add_or_replace_parameter def process_links(links): for link in links: link.url = url_query_cleaner(link.url) yield link class myCrawler(CrawlSpider): name = 'symphony' allowed_domains = ['theshell.org'] start_urls = ['https://www.theshell.org/'] base_url = 'https://www.theshell.org/' custom_settings = { 'DOWNLOADER_MIDDLEWARES': {'sitescrapper.middlewares.RotateUserAgentMiddleware': 400, }, 'COOKIES_ENABLED': False, 'CONCURRENT_REQUESTS': 6, 'DOWNLOAD_DELAY': 1, 'ITEM_PIPELINES': {'sitescrapper.pipelines.DuplicatesPipeline': 300}, 'FEEDS': {'csv_file.csv': {'format': 'csv'}} } rules = ( Rule( LinkExtractor(allow_domains='theshell.org', deny=[r'calendar'], ), process_links=process_links, callback='parse_item', follow=True ), ) def parse_infinite_scroll(self, response): # 解析当前页内容,和普通页逻辑一致 yield { 'url': response.url, 'html_data': response.text } # 递推构造下一页请求,以下逻辑需替换为你抓包拿到的实际接口规则 current_page = response.meta.get('page', 1) next_page = current_page + 1 # 终止条件:当前页无有效内容时停止递推,选择器替换成实际的内容节点选择器 if len(response.xpath('//div[@class="list-item"]')) > 0: next_url = add_or_replace_parameter(response.url, 'page', next_page) yield Request( url=next_url, callback=self.parse_infinite_scroll, meta={'page': next_page} ) def parse_item(self, response): # 匹配无限滚动类页面的路径规则,交给专门的解析逻辑 if re.match(r'https://www.theshell.org/.*/list/.*', response.url): yield from self.parse_infinite_scroll(response) return # 普通页面走原有解析逻辑 yield { 'url': response.url, 'html_data':response.text }
注意:代码里的分页参数规则、内容判空选择器、无限滚动页面的路径匹配规则,都要替换成目标站点实际的逻辑,不要直接照搬。
接口加密场景的备选方案
如果抓到的接口有动态签名、必须执行JS才能生成合法请求参数,再接入scrapy-playwright做页面渲染:
- 安装依赖:执行
pip install scrapy-playwright && playwright install chromium - 在配置中开启playwright下载器中间件,对需要处理无限滚动的页面传入Playwright页面对象,注入JS脚本自动滚动到底部,直到页面高度不再变化(即无新内容加载),再返回完整渲染后的页面内容给解析函数。
该方案请求速度远低于接口直连,仅适合接口加密无法破解的场景。
无限滚动页面的判断标准
- 初始返回的HTML中列表内容仅展示前10-20条,页面底部无传统分页按钮(如下一页、页码跳转控件)
- 滚动到底部时会出现加载动画,同时网络面板出现新的XHR/Fetch请求
- 页面源码中可监听到
scroll事件绑定的加载逻辑。
内容的提问来源于stack exchange,提问作者imhans4305
相关产品推荐
相关产品推荐

