如何使用Flutter抓取动态数据?附Python Selenium迁移代码
在Flutter中实现类似Selenium的动态数据抓取
方案选择
Flutter本身是跨端UI框架,要抓取JS渲染的动态数据,有两个主流方案:
- 使用puppeteer Dart包:模拟无头浏览器,和你原Python代码的Selenium逻辑最接近,适合后台/命令行场景
- 使用webview_flutter包:在Flutter应用中嵌入WebView,加载页面后注入JS获取元素内容,适合移动端APP内抓取
下面分别给出对应实现:
方案1:使用puppeteer(与原Selenium逻辑匹配度最高)
这个包可以直接控制Chrome/Chromium,实现和Selenium几乎一致的操作流程。
步骤:
- 在
pubspec.yaml中添加依赖:
dependencies: puppeteer: ^3.0.0
- 编写核心代码:
import 'package:puppeteer/puppeteer.dart'; void main() async { // 启动Chrome浏览器(headless设为false可显示窗口,调试更直观) final browser = await puppeteer.launch(headless: false); // 打开新页面 final page = await browser.newPage(); // 访问目标Udemy课程页面 await page.goto('https://www.udemy.com/course/js-algorithms-and-data-structures-masterclass/?couponCode=ST21MT61124'); // 等待目标元素加载完成(确保JS渲染完毕) await page.waitForSelector('.ud-heading-lg'); // 通过JS注入获取元素文本内容 final elementText = await page.evaluate('''() => { return document.querySelector('.ud-heading-lg').textContent.trim(); }'''); print(elementText); // 关闭浏览器 await browser.close(); }
方案2:使用webview_flutter(适合移动端APP场景)
如果是在Flutter移动端APP内需要抓取数据,可以用WebView加载页面后注入JS提取内容。
步骤:
- 添加依赖:
dependencies: webview_flutter: ^4.4.0
- 实现代码(简化版):
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('动态数据抓取')), body: const WebViewExample(), ), ); } } class WebViewExample extends StatefulWidget { const WebViewExample({super.key}); @override State<WebViewExample> createState() => _WebViewExampleState(); } class _WebViewExampleState extends State<WebViewExample> { late final WebViewController controller; @override void initState() { super.initState(); controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..loadRequest(Uri.parse('https://www.udemy.com/course/js-algorithms-and-data-structures-masterclass/?couponCode=ST21MT61124')) ..addJavaScriptChannel( 'DataChannel', onMessageReceived: (JavaScriptMessage message) { // 接收JS返回的元素文本 print(message.message); }, ) ..setNavigationDelegate( NavigationDelegate( onPageFinished: (String url) async { // 页面加载完成后注入JS获取目标元素 await controller.runJavaScript(''' const element = document.querySelector('.ud-heading-lg'); if (element) { DataChannel.postMessage(element.textContent.trim()); } '''); }, ), ); } @override Widget build(BuildContext context) { return WebViewWidget(controller: controller); } }
注意事项
- 遵守目标网站的服务条款和
robots.txt规则,避免违规抓取 - 若遇到反爬机制(如Cloudflare验证),需额外配置User-Agent、Cookie等参数,puppeteer支持设置这类配置
- 使用puppeteer时,需确保本地有Chrome/Chromium环境,或配置远程浏览器地址
内容的提问来源于stack exchange,提问作者bishoy alper
相关产品推荐
相关产品推荐

