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

如何通过Flutter进行网页抓取(Web Scraping)并展示IP详情至应用UI?

从ipcost.com抓取IP数据并在Flutter应用中展示

一、实现IP数据抓取

在Flutter中可以通过http库请求网页内容,搭配html库解析DOM节点来获取IP详情。

1. 添加依赖

在项目的pubspec.yaml文件中添加以下依赖:

dependencies:
  http: ^1.1.0
  html: ^0.15.4

执行flutter pub get完成依赖安装。

2. 编写抓取逻辑

先定义IP数据模型,再实现网页请求与解析的函数:

import 'package:http/http.dart' as http;
import 'package:html/parser.dart' as parser;
import 'package:html/dom.dart' as dom;

// IP详情数据模型
class IpDetails {
  final String ip;
  final String country;
  final String region;
  final String city;
  final String isp;

  IpDetails({
    required this.ip,
    required this.country,
    required this.region,
    required this.city,
    required this.isp,
  });
}

// 抓取IP详情的异步函数
Future<IpDetails?> fetchIpDetails() async {
  try {
    final response = await http.get(Uri.parse('https://ipcost.com'));
    if (response.statusCode == 200) {
      final document = parser.parse(response.body);
      
      // 注意:需根据ipcost.com实际DOM结构调整选择器,以下为示例
      final ipElement = document.querySelector('div.ip-detail > span.ip-value');
      final countryElement = document.querySelector('div.country-info > span.value');
      final regionElement = document.querySelector('div.region-info > span.value');
      final cityElement = document.querySelector('div.city-info > span.value');
      final ispElement = document.querySelector('div.isp-info > span.value');

      if (ipElement != null && countryElement != null && regionElement != null && cityElement != null && ispElement != null) {
        return IpDetails(
          ip: ipElement.text.trim(),
          country: countryElement.text.trim(),
          region: regionElement.text.trim(),
          city: cityElement.text.trim(),
          isp: ispElement.text.trim(),
        );
      }
    }
    return null;
  } catch (e) {
    print('抓取失败:$e');
    return null;
  }
}

提示:打开ipcost.com的开发者工具,定位到目标数据对应的HTML元素,替换上述代码中的选择器,确保能正确解析数据。

二、在UI中展示数据

使用FutureBuilder处理异步请求,实现数据的加载状态展示:

import 'package:flutter/material.dart';

class IpInfoPage extends StatelessWidget {
  const IpInfoPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('我的IP详情')),
      body: FutureBuilder<IpDetails?>(
        future: fetchIpDetails(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return Center(child: Text('加载出错:${snapshot.error}'));
          } else if (snapshot.hasData && snapshot.data != null) {
            final ipData = snapshot.data!;
            return Padding(
              padding: const EdgeInsets.all(16.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  _buildInfoItem('IP地址', ipData.ip),
                  const SizedBox(height: 12),
                  _buildInfoItem('国家', ipData.country),
                  const SizedBox(height: 12),
                  _buildInfoItem('地区', ipData.region),
                  const SizedBox(height: 12),
                  _buildInfoItem('城市', ipData.city),
                  const SizedBox(height: 12),
                  _buildInfoItem('运营商', ipData.isp),
                ],
              ),
            );
          } else {
            return const Center(child: Text('未获取到IP数据'));
          }
        },
      ),
    );
  }

  // 封装信息行组件
  Widget _buildInfoItem(String label, String value) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        SizedBox(
          width: 80,
          child: Text(
            '$label:',
            style: const TextStyle(fontWeight: FontWeight.bold),
          ),
        ),
        Expanded(child: Text(value)),
      ],
    );
  }
}

三、注意事项

  • 页面结构变更:如果ipcost.com更新网页布局,需重新调整DOM选择器,否则抓取逻辑会失效。
  • 请求限制:频繁请求可能触发网站的反爬机制,建议添加请求间隔或本地缓存。
  • 权限配置:Android需在AndroidManifest.xml中添加网络权限:<uses-permission android:name="android.permission.INTERNET"/>;iOS无需额外配置(目标网站为HTTPS)。

内容的提问来源于stack exchange,提问作者Esmaeil Ahmadipour

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:40:19