如何用scrapy-selenium实现加载更多分页,获取响应却爬取不到内容怎么解决?
问题原因
- 未等待异步加载完成:点击「加载更多」按钮后,页面请求新数据、渲染新节点需要一定时间,代码未做任何等待直接读取当前
page_source,此时新内容还未插入DOM结构,XPath无法匹配到对应节点,最终返回空结果。 - 初始页面内容漏爬:现有逻辑是先执行点击加载更多操作,再提取节点数据,页面首次加载完成就已经渲染的第一批内容被完全跳过,没有被爬取。
- 点击逻辑稳定性不足:使用ActionChains的
move_to_element+click组合,在元素未完全进入视口、被其他元素遮挡的场景下容易出现点击失效,没有触发新内容加载。 - 变量命名风险:使用
next作为变量名覆盖了Python内置的next()函数,可能引发不可预知的异常。
修复方案
- 进入页面后先提取首次渲染的内容,再执行加载更多的循环逻辑,避免漏爬首屏数据
- 点击加载更多后添加显式等待,通过页面高度变化、节点数量变化判断新内容是否加载完成,不要使用固定时长的
sleep - 替换点击逻辑,优先使用JS执行点击操作,避免元素交互限制导致的点击失效
- 新增加载失败兜底逻辑,避免按钮存在但无法点击时进入死循环
修正后代码
import scrapy from scrapy.selector import Selector from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from time import sleep class ProductSpider(scrapy.Spider): name = "card" start_urls = ['https://examplesite.com'] def __init__(self): self.driver = webdriver.Chrome() # 显式等待最长时间,可根据页面加载速度调整 self.wait = WebDriverWait(self.driver, 10) def parse(self, response): self.driver.get(response.url) # 先提取首屏已加载的内容 for item in self.extract_content(self.driver.page_source): yield item # 记录当前页面高度,用于判断是否加载出新内容 last_height = self.driver.execute_script("return document.body.scrollHeight") while True: # 查找加载更多按钮 show_more_btns = self.driver.find_elements_by_css_selector("button#show-more") # 按钮不存在、或按钮已禁用则终止循环 if not show_more_btns or not show_more_btns[0].is_enabled(): break show_more_btn = show_more_btns[0] # 滚动到按钮位置 self.driver.execute_script("arguments[0].scrollIntoView();", show_more_btn) # 用JS执行点击,避免元素交互限制 self.driver.execute_script("arguments[0].click();", show_more_btn) try: # 等待页面高度变化,确认新内容加载完成 self.wait.until( lambda d: d.execute_script("return document.body.scrollHeight") > last_height ) # 更新页面高度 last_height = self.driver.execute_script("return document.body.scrollHeight") # 提取新加载的内容 for item in self.extract_content(self.driver.page_source): yield item except: # 超时未加载出新内容,终止循环 break self.driver.close() def extract_content(self, page_source): """单独封装内容提取逻辑""" lists = Selector(text=page_source) for item in lists.xpath('//ul[@id="finder-table"]/li'): yield{ 'Name': item.xpath('.//*[@class="table-item-heading-product-name"]/span/strong/text()').get(), 'Title': item.xpath('.//*[@class="table-item-heading-product-name"]/span/text()').get() }
如果修改后还是无法提取到内容,可以先打印self.driver.page_source检查实际渲染的DOM结构,确认XPath选择器和页面实际结构是否匹配。
内容的提问来源于stack exchange,提问作者Md. Fazlul Hoque
相关产品推荐
相关产品推荐

