使用Rails和Nokogiri爬取带滚动懒加载网站的技术疑问
思路拆解:处理带复杂参数的懒加载数据爬取
嘿,这个场景我之前折腾过好几次,咱们慢慢捋清楚~
首先直接回答你的核心问题:能不能靠滚动两次拿到所有数据?得看网站的实际数据量。如果网站的内容刚好分两批加载完,那当然可以;但绝大多数懒加载网站是每次滚动加载一批,直到没有更多内容为止,这种情况下固定两次滚动大概率拿不全。所以更靠谱的思路是「动态判断是否还有数据,循环加载」,而不是固定次数。
下面给你几个具体的实现方向,结合Rails+Nokogiri的技术栈:
1. 先摸清楚AJAX请求的规律
第一步一定要打开浏览器的开发者工具(F12),切换到「Network」标签,过滤「XHR」请求,然后手动滚动页面,观察每次触发的load_more请求:
- 重点看
lastPostid参数的变化:这个值基本就是当前页面最后一条内容的ID,下一次请求会用它来告诉服务器「我要加载这条之后的内容」 - 留意请求返回的内容:当服务器返回空数据、或者某个标识(比如
has_more: false)的时候,就说明没有更多内容可以加载了
搞清楚这个规律,后面不管是模拟滚动还是直接请求接口,都有了依据。
2. 两种实现方案供你选
方案A:模拟真实滚动(适合需要完整渲染页面的场景)
因为Nokogiri只能解析静态HTML,没法处理JS触发的懒加载,所以需要结合Capybara+Selenium来模拟浏览器行为:
# 用Capybara打开目标页面 visit '目标网站URL' loop do # 滚动到页面底部 execute_script 'window.scrollTo(0, document.body.scrollHeight)' # 等待AJAX加载完成(可以根据页面元素调整等待条件) sleep 2 # 或者用Capybara的wait_until等待新元素出现 # 检查是否还有更多数据(比如找页面上的「加载更多」按钮是否还存在,或者新内容是否加载) break if page.has_no_css?('.加载更多按钮的选择器') || 新内容数量不再增加 end # 此时页面已经加载了所有内容,用Nokogiri解析 html = Nokogiri::HTML(page.body) # 提取你需要的数据...
方案B:直接构造AJAX请求(效率更高)
如果能摸清楚load_more接口的参数规律,直接用HTTP库(比如Faraday、HTTParty)请求接口,比模拟滚动快得多:
require 'faraday' require 'nokogiri' conn = Faraday.new(url: '网站基础URL') do |faraday| faraday.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' # 模拟浏览器UA end last_post_id = '初始的lastPostid值(第一次请求可以从页面HTML里提取)' base_id = '1837373' # 这个id如果固定的话就直接用,不固定就从页面提取 all_data = [] loop do response = conn.get("/load_more?id=#{base_id}&lastPostid=#{last_post_id}") # 解析返回的内容(如果是HTML片段) doc = Nokogiri::HTML(response.body) items = doc.css('.内容项的选择器') break if items.empty? # 没有新内容就停止循环 all_data += items.map { |item| 提取item的信息 } # 更新last_post_id为当前这批内容的最后一个ID last_post_id = items.last.attr('data-post-id') # 假设ID存在于data属性里 sleep 1 # 加个延迟,避免触发反爬 end # 处理all_data...
3. 避坑提醒
- 反爬机制:很多网站会限制请求频率,记得加随机延迟,不要请求太频繁;尽量带上和浏览器一致的请求头(比如User-Agent、Cookie)
- 参数变化:有些网站的
id参数可能不是固定的,要从初始页面的HTML里提取(比如用Nokogiri解析初始页面,找到隐藏的参数值) - 异常处理:请求可能会失败,记得加rescue块处理网络错误、解析错误等情况
回到最开始的问题,固定两次滚动只有在数据量刚好两批的时候才有用,实际场景中还是循环判断更可靠~
内容的提问来源于stack exchange,提问作者Oğuz Çiçek
相关产品推荐
相关产品推荐

