极简Dart代码搞定App内实时数据抓取

嘿,这个 Flutter 小工具教你如何用 Dart 语言在手机应用里快速抓取网络数据!就像个迷你爬虫,能自动从网站获取内容并展示出来。你可以用它来抓取文章、图片或者任何公开信息,特别适合需要实时更新数据的应用场景,操作简单又实用!

下面是一个完整的 Flutter 应用示例,展示如何使用 Dart 在 Flutter 应用中实现轻量级数据抓取功能。这个示例从公共 API 获取数据并展示,同时包含简单的 HTML 解析功能。

php 复制代码
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:html/parser.dart' as parser;
import 'package:html/dom.dart';
​
void main() {
  runApp(MyApp());
}
​
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dart 数据抓取示例',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: DataFetchingExample(),
    );
  }
}
​
class DataFetchingExample extends StatefulWidget {
  @override
  _DataFetchingExampleState createState() => _DataFetchingExampleState();
}
​
class _DataFetchingExampleState extends State<DataFetchingExample> {
  List<Post> posts = [];
  bool isLoading = false;
  String errorMessage = '';
​
  // 从 JSON API 获取数据
  Future<void> fetchJsonData() async {
    setState(() {
      isLoading = true;
      errorMessage = '';
    });
​
    try {
      final response = await http.get(
        Uri.parse('https://jsonplaceholder.typicode.com/posts'),
        headers: {
          'User-Agent': 'MyFlutterApp/1.0',
        },
      );
​
      if (response.statusCode == 200) {
        final List<dynamic> data = json.decode(response.body);
        setState(() {
          posts = data.map((json) => Post.fromJson(json)).toList();
          isLoading = false;
        });
      } else {
        setState(() {
          errorMessage = '获取数据失败: ${response.statusCode}';
          isLoading = false;
        });
      }
    } catch (e) {
      setState(() {
        errorMessage = '发生错误: $e';
        isLoading = false;
      });
    }
  }
​
  // 解析 HTML 内容示例
  Future<void> fetchAndParseHtml() async {
    setState(() {
      isLoading = true;
      errorMessage = '';
    });
​
    try {
      final response = await http.get(
        Uri.parse('https://httpbin.org/html'),
        headers: {
          'User-Agent': 'MyFlutterApp/1.0',
        },
      );
​
      if (response.statusCode == 200) {
        final document = parser.parse(response.body);
        final Element? h1Element = document.querySelector('h1');
        
        setState(() {
          posts = [
            Post(
              id: 1,
              title: 'HTML 解析示例',
              body: h1Element?.text ?? '未找到H1标签',
            )
          ];
          isLoading = false;
        });
      } else {
        setState(() {
          errorMessage = '获取HTML失败: ${response.statusCode}';
          isLoading = false;
        });
      }
    } catch (e) {
      setState(() {
        errorMessage = '解析HTML时发生错误: $e';
        isLoading = false;
      });
    }
  }
​
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Dart 数据抓取示例'),
        backgroundColor: Colors.blue[700],
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                  onPressed: fetchJsonData,
                  child: Text('获取JSON数据'),
                  style: ElevatedButton.styleFrom(
                    primary: Colors.green,
                  ),
                ),
                ElevatedButton(
                  onPressed: fetchAndParseHtml,
                  child: Text('解析HTML'),
                  style: ElevatedButton.styleFrom(
                    primary: Colors.orange,
                  ),
                ),
              ],
            ),
            SizedBox(height: 20),
            Text(
              '数据抓取结果:',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 10),
            if (isLoading)
              Center(child: CircularProgressIndicator())
            else if (errorMessage.isNotEmpty)
              Container(
                padding: EdgeInsets.all(12),
                color: Colors.red[50],
                child: Text(
                  errorMessage,
                  style: TextStyle(color: Colors.red),
                ),
              )
            else if (posts.isEmpty)
              Text('点击上方按钮获取数据')
            else
              Expanded(
                child: ListView.builder(
                  itemCount: posts.length,
                  itemBuilder: (context, index) {
                    return Card(
                      margin: EdgeInsets.symmetric(vertical: 8),
                      child: ListTile(
                        title: Text(
                          posts[index].title,
                          style: TextStyle(fontWeight: FontWeight.bold),
                        ),
                        subtitle: Text(posts[index].body),
                        leading: CircleAvatar(
                          child: Text(posts[index].id.toString()),
                        ),
                      ),
                    );
                  },
                ),
              ),
          ],
        ),
      ),
    );
  }
}
​
// 数据模型
class Post {
  final int id;
  final String title;
  final String body;
​
  Post({required this.id, required this.title, required this.body});
​
  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      id: json['id'],
      title: json['title'],
      body: json['body'],
    );
  }
}

使用说明

1、这个示例展示了两种数据抓取方式:

  • 从JSON API获取数据
  • 解析HTML内容

2、要运行此代码,需要在pubspec.yaml中添加以下依赖:

yaml 复制代码
dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.5
  html: ^0.15.1

3、运行flutter pub get安装依赖

注意事项

1、在Flutter应用中执行网络请求时,Android和iOS平台需要添加网络权限:

  • Android: 在android/app/src/main/AndroidManifest.xml中添加<uses-permission android:name="android.permission.INTERNET"/>
  • iOS: 在ios/Runner/Info.plist中添加<key>NSAppTransportSecurity</key><dict><key>NSAllowsArbitraryLoads</key><true/></dict>

2、对于更复杂的数据抓取需求,可以考虑使用以下Dart包:

  • dio: 更强大的HTTP客户端
  • html: 用于解析HTML内容
  • csslib: 用于解析CSS选择器

3、在实际应用中,请确保遵守目标网站的robots.txt规则和服务条款

这个示例展示了Dart在Flutter应用中实现轻量级数据抓取的实用性,特别适合需要快速获取并展示简单数据的应用场景。

总之,用 Dart 做轻量级数据抓取还是挺方便的,尤其是在 Flutter 应用里直接使用。虽然比不上 Python 那种专业爬虫的强大功能,但对于日常简单的数据获取需求完全够用了。感兴趣的话可以自己动手试试哦!

相关推荐
小白学大数据10 小时前
分布式爬虫的全局请求间隔协调与IP轮换策略
分布式·爬虫·tcp/ip
花花无缺10 小时前
函数和方法的区别
java·后端·python
Brian-coder10 小时前
机器学习与深度学习的 Python 基础之 NumPy(2)
python·深度学习·机器学习
Cold_Rain0210 小时前
利用 Python 绘制环形热力图
python·数学建模·数据可视化
在钱塘江10 小时前
LangGraph从新手到老师傅 - 3 - StateGraph基础入门
人工智能·python
感哥10 小时前
Django用户认证权限
python·django
思辨共悟10 小时前
python数据分析 与spark、hive数据分析对比
python·数据分析·spark
aiden:)10 小时前
Selenium WebUI 自动化“避坑”指南——从常用 API 到 10 大高频问题
开发语言·前端·javascript·python·selenium
Lenskit10 小时前
使用pyspark对上百亿行的hive表生成稀疏向量
python·spark-ml·spark