Dart语言基于Puppeteer抓取Google Finance行情报价始终返回固定值的修复咨询
固定值问题核心原因及修复方案
- 核心原因1:Google Finance行情数据为异步渲染,
page.goto默认等待load事件完成时,行情元素还未加载,此时抓取要么拿到旧缓存占位值,要么拿到上一轮的DOM残留,对应反复输出的固定$2,254.84。 - 核心原因2:Puppeteer默认启用浏览器HTTP缓存,第二轮循环跳转同一URL时直接返回缓存的旧HTML,不会发起新请求。
- 核心原因3:依赖Google动态生成的CSS类
P6K39c,类名随时可能变更,且硬编码按含$元素顺序赋值的逻辑不稳定,容易错位匹配到错误的固定值。 - 额外错误:股票列表
APPL为拼写错误,正确代码为AAPL,特斯拉对应的代码为TSLA而非TESLA,跳转错误地址会直接返回404页面。
修复后可运行的代码
import 'dart:io' as io; import 'dart:math'; import 'package:puppeteer/puppeteer.dart' as pp; void main() async { // 启动时禁用浏览器缓存,关闭自动化特征检测 var launch = await pp.puppeteer.launch( executablePath: "/usr/bin/brave-browser", args: [ '--disable-cache', '--disable-application-cache', '--disable-offline-load-stale-cache', '--disk-cache-size=0', ], headless: true, // 如需可见窗口可改为false ); var stocks_nasdaq = ["GOOG", "MSFT", "AAPL", "TSLA"]; // 修正拼写错误的股票代码 var page = await launch.newPage(); // 全局禁用页面缓存 await page.setCacheEnabled(false); while (true) { for (var asset in stocks_nasdaq) { // 加随机查询参数避免URL缓存命中 final cacheBuster = Random().nextInt(999999); await page.goto( "https://www.google.com/finance/quote/$asset:NASDAQ?cb=$cacheBuster", waitUntil: pp.PageWaitUntil.networkidle2, // 等待页面网络请求空闲,确保异步行情数据加载完成 ); // 等待核心行情元素加载完成,用稳定的属性选择器替代动态类 await page.waitForSelector("div[data-last-price]", timeout: Duration(seconds: 10)); // 直接获取结构化的行情数据,无需遍历DOM匹配含$元素 final priceData = await page.evaluate(''' () => { const priceEl = document.querySelector('div[data-last-price]'); const changeEl = document.querySelector('.JwB6zf'); const yearChangeEl = document.querySelectorAll('.P6K39c')[2]; return { current_price: priceEl?.getAttribute('data-last-price'), 24h_change: changeEl?.textContent, year_change: yearChangeEl?.textContent } } '''); print("$asset 行情:$priceData"); await Future.delayed(Duration(seconds: 10)); // 替代同步阻塞的io.sleep } } }
关键修复点说明
- 启动参数增加多维度禁用缓存配置,同时全局设置页面缓存禁用,彻底避免旧HTML命中缓存。
- 每次跳转URL加随机
cb参数,进一步确保不会复用旧响应。 waitUntil改为networkidle2,等待页面异步行情数据请求完成后再执行抓取,不会拿到加载前的占位值。- 用*
data-last-price*这个固定属性选择器替代动态类P6K39c,该属性直接存储最新行情数值,不受前端类名变更影响。 - 把同步阻塞Dart事件循环的
io.sleep换成异步的Future.delayed,避免页面渲染阻塞。
内容的提问来源于stack exchange,提问作者Burugu Anudeep
相关产品推荐
相关产品推荐

