You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter爬取Trenord列车信息遇Cookie弹窗问题求助

解决Flutter跨平台爬取Trenord列车数据的问题

方案1:手动添加Cookie授权标识

网站的Cookie弹窗本质是要求会话中携带特定Cookie值,可通过以下步骤绕过:

  • 用浏览器打开目标链接,点击同意Cookie后,在开发者工具的Application标签中找到网站设置的Cookie,记录下类似cookie_consent=accepted这类核心授权Cookie的键值对。
  • 在Flutter的HTTP请求中手动添加这些Cookie和浏览器UA,模拟正常访问:
import 'package:http/http.dart' as http;

Future<void> fetchTrainPage() async {
  final url = Uri.parse('https://www.trenord.it/store/#/en/booking/step1?departure=MILANO%20PORTA%20GARIBALDI&destination=MILANO%20BOVISA%20POLITECNICO&from=20241211&fromstart=08:58');
  final response = await http.get(
    url,
    headers: {
      'Cookie': 'cookie_consent=accepted; 替换为实际抓取到的其他必要Cookie',
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
    },
  );
  // 处理返回的页面内容
  print(response.body);
}

方案2:用WebView跨平台处理Cookie授权

利用Flutter的WebView组件在全平台加载页面,自动处理Cookie弹窗后抓取内容,步骤如下:

  1. 在pubspec.yaml添加依赖:
dependencies:
  webview_flutter: ^4.4.0
  1. 实现WebView页面,模拟点击Cookie同意按钮并获取HTML:
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class TrainScraperPage extends StatefulWidget {
  const TrainScraperPage({super.key});

  @override
  State<TrainScraperPage> createState() => _TrainScraperPageState();
}

class _TrainScraperPageState extends State<TrainScraperPage> {
  late WebViewController _controller;

  @override
  void initState() {
    super.initState();
    _controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..loadRequest(Uri.parse('https://www.trenord.it/store/#/en/booking/step1?departure=MILANO%20PORTA%20GARIBALDI&destination=MILANO%20BOVISA%20POLITECNICO&from=20241211&fromstart=08:58'))
      ..addJavaScriptChannel(
        'PageScraper',
        onMessageReceived: (message) {
          // 拿到完整页面HTML
          final pageHtml = message.message;
          // 后续解析列车数据逻辑
          print(pageHtml);
        },
      )
      ..setNavigationDelegate(
        NavigationDelegate(
          onPageFinished: (url) async {
            // 替换为实际的Cookie同意按钮选择器(用浏览器开发者工具查看)
            await _controller.runJavaScript('document.querySelector("button.accept-cookie-btn").click();');
            // 等待页面更新
            await Future.delayed(const Duration(seconds: 2));
            // 获取页面HTML并传递到Flutter端
            await _controller.runJavaScript('PageScraper.postMessage(document.documentElement.outerHTML);');
          },
        ),
      );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: WebViewWidget(controller: _controller),
    );
  }
}

注意:需要用浏览器开发者工具查看Cookie同意按钮的CSS选择器,替换代码中的选择器字符串。

方案3:直接调用网站内部API(推荐)

票务网站通常会用API加载列车数据,比爬HTML更稳定:

  • 打开浏览器开发者工具的Network标签,刷新目标页面,过滤XHR/fetch请求,找到加载列车列表的API接口。
  • 查看该API的请求方法、参数、请求头,直接在Flutter中调用:
import 'package:http/http.dart' as http;
import 'dart:convert';

Future<void> fetchTrainDataViaApi() async {
  // 替换为实际抓取到的API地址
  final apiUrl = Uri.parse('https://www.trenord.it/api/booking/get-trains');
  final headers = {
    'Cookie': 'cookie_consent=accepted',
    'Content-Type': 'application/json',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
  };
  final body = jsonEncode({
    'departure': 'MILANO PORTA GARIBALDI',
    'destination': 'MILANO BOVISA POLITECNICO',
    'date': '20241211',
    'time': '08:58'
    // 替换为API要求的实际参数
  });

  final response = await http.post(apiUrl, headers: headers, body: body);
  final trainData = jsonDecode(response.body);
  // 直接处理结构化数据
  print(trainData);
}

内容的提问来源于stack exchange,提问作者Simone Sesana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 17:35:20