文章

flutter使用DOM解析

本文主要是记录在写 flutter 项目的时候如果碰到比较好的、比较适用的网页,而该网页又没有提供专门的 RESTful 风格的接口的时候,此时使用本教程解析 html 可以很好地获取自己想要的数据,跟爬虫的解析有异曲同工之妙!话不多说,开整!

一、技术选型和初始准备:

首先引入本次教程所需要的依赖包:

1
2
3
dependencies:
  html: ^0.14.0+4
  dio: ^3.0.10

此处使用了两个包, 一个是 html 包,该包主要是用来解析 html标签 的。另外一个包 dio,该包用来发起请求的,这个包很常见,就不细说了。

二、发起请求获取所有的 html源码

首先通过 dio 发起请求获取要爬取的网页页面,此处以掘金首页的导航为准做个小例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/// 存放标签
  List<String> tags = [];
  /// 存放标签跳转路径
  List<String> tagUrls = [];
  
  @override
  void initState() {
    /// 初始化的时候将标签、标签路径清空
    this.tagUrls = [];
    this.tags = [];
    getPost();
    super.initState();
  }

  getPost() async {
    Dio dio = new Dio();
    // 发起请求获取首页的html数据
    Response res = await dio.get("https://juejin.cn/android");
    // 解析标签的值
    List titles = parse(res.data).querySelectorAll("li.nav-item > a ");
    // 添加标签到集合
    titles.forEach((element) {
      this.setState(() {
        this.tags.add(element.text.trim());
        this.tagUrls.add(element.attributes['href']);
      });
      print(element.text.trim() + ">>>>" + element.attributes['href']);
    });
  }


 @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is cal
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Wrap(
              runSpacing: 5,
              spacing: 4,
              children: List.generate(
                  tags.length,
                  (index) => Container(
                        padding:
                            EdgeInsets.symmetric(horizontal: 10, vertical: 5),
                        decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(6),
                            color: Colors.pinkAccent),
                        child: Text(
                          tags[index],
                          style: TextStyle(color: Colors.white),
                        ),
                      )),
            ),
          ],
        ),
      ),
    );
  }

三、说明一下 html 的使用方法:

  • 要保证parse的是一个标准的 Document文件,也就是说你 parse的肯定是在浏览器中可以打开且正确的html源码,否则会 parse失败!
  • 引包着重说一下,这里的包只需要引入如下即可:
1
2
import 'package:html/parser.dart' show parse;
import 'package:dio/dio.dart';
  • 再一个就是解析的标签有如下说明:
    • document.querySelectorAll(".xxx"): 获取所有样式为 xxx 的标签列表;
    • document.querySelectorAll(".xxx>div>p.example"):获取样式为 xxx的标签下面含有divdiv下面包含的样式为 examplep标签的列表,(就一句话前面两个大于号是一味最后的 p标签 做规则限制的;
    • document.querySelectorAll(".xxx")[0].text.strim():获取标签下面的值,比如:<div class=xxx>hello</div>
    • document.querySelectorAll(a)[0].attributes['href']: 获取 a标签的跳转地址;
本文由作者按照 CC BY 4.0 进行授权