Flutter. Посылаем http запросы и парсим их.

Предисловие.

В этой статье, я расскажу как посылать запросы на сайт и парсить его содержимое. В сущности, вы получите тот же requests+bs4 из Python, только под Flutter и на языке Dart. Таким образом, вы без особого труда, сможете написать бота под большинство сайтов, автоматизируя рутинные действия, и делая свою жизнь проще.

Подготовка.

Сперва, нужно установить библиотеки. Для этого, в папке с проектом, откройте pubspec.yaml, и в dependencies добавьте 3 библиотеки:

dependencies:
  requests: ^4.4.1
  http: ^0.13.4
  html: ^0.15.0
  flutter:
    sdk: flutter

При добавлении библиотек, синтаксис следующий:

название_библиотеки: ^его_версия

К тому времени когда вы наткнетесь на эту статью, версии библиотек могут устареть. Поэтому, найдите эту библиотеку на pub.dev (хранилище библиотек, аналог pypi.org для python), зайдите в графу Installing, и скопируйте свежую комманду.

Ссылки на библиотеки:

  • requests — порт Python библиотеки requests, на язык Dart. По функционалу, мало отличается от библиотеки http.
  • http — позволяет отправлять http запросы.
  • html — дает доступ к DOM страницы, имеет тот же синтаксис что и в JS (querySelector, innerHtml и т.д).

Теперь, сохраните pubspec.yaml, и библиотеки погрузятся в ваш проект.

Далее, скопируйте данный код к себе в проект.

Исходный код

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:html/parser.dart';
import 'package:requests/requests.dart';
import 'package:http/http.dart' as http;
void main() {
  runApp(
    MaterialApp(
      routes: {
        '/': (BuildContext context) {
          return NewWidget();
        },
      },
    ),
  );
}
class NewWidget extends StatefulWidget {
  const NewWidget({
    Key? key,
  }) : super(key: key);
  @override
  State createState() => _NewWidgetState();
}
class _NewWidgetState extends State {
  String _data = "no data";
  getData() async {
    
    setState(() {});
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Requests Tutorial"),
      ),
      body: Container(
        color: Colors.greenAccent,
        child: Column(
          children: [
            Center(
              child: ElevatedButton(
                onPressed: () {
                  getData();
                },
                child: Text("Get Data"),
              ),
            ),
            Text("$_data"),
          ],
        ),
      ),
    );
  }
}

Посылаем запросы с помощью библиотеки http.

Тестировать запросы будем в методе getData, туда добавьте следующий код:

Uri uri = Uri.parse("https://google.com"); //Конвертируем url в uri
var resp = await http.get(uri); //посылаем get запрос на google.com, передам uri
_data = resp.body; //присваиваем полученный код страницы, переменной _data

Весь код, я объяснил в комментариях.

Теперь, запустите, и нажмите кнопку Get Data.

В итоге, получили код страницы. Вы также, можете передать заголовки в запрос, в них же, передаются и куки.

var resp = await http.get(uri, 
  headers: <String, String>{
  'Content-Type': 'application/json; charset=UTF-8',
  });

Также, вы можете отправить post запрос.

var resp = await http.post(Uri.parse('https://google.com'),
  headers: <String, String>{
    'Content-Type': 'application/json; charset=UTF-8',
  },
  body: "123"
);

Данные post запроса, указываются в аргументе body.

Еще, доступны запросы DELETE, HEAD, PATCH, PUT, подробнее в документации.

Посылаем запросы с помощью Requests.

Те кто пришли сюда из Python, наверняка, будут рады увидеть знакомую библиотеку.

Попробуем послать GET запрос.

var resp = await Requests.get("https://google.com");
resp.raiseForStatus(); //Вернуть ошибку при неудачном подключении
_data = resp.content(); //Вернули код html страницы

В данном коде, я послал запрос на сайт google.com, на всякий случай, сделал проверку правильности подключения, и вывел полученный html код.

POST запросы здесь передаются также, как в библиотеке http, только здесь, передается url-строка вместо uri.

var r = await Requests.post(
  'https://reqres.in/api/users',
  body: {
    'userId': 10,
    'id': 91,
    'title': 'aut amet sed',
  },

Подробнее в документации.

Парсим страницу.

Передайте код страницы в функцию parse, чтобы получить доступ к DOM дереву, и начать парсить данные с сайта.

var document = parse(resp.body);

Теперь, вы можете получить содержимое любого элемента html страницы, при помощи querySelectorAll (прямо как в JS).

var elem = document.querySelectorAll("div")[0];

В querySelectorAll нужно передать css селектор, который можно получить в браузере Mozilla Firefox.

Для этого, откройте инструменты разработчика (F12). Далее, нажмите эту кнопку:

Нажмите по нужному вам элементу, и он, подсветится в коде страницы.

После чего, кликните ПКМ по элементу и выберите Copy->CSS Selector.

Ок, осталось получить содержимое элемента.

_data = elem.innerHtml;

Запросы для ленивых Flutter Edition.

Зайдите на сайт через Mozilla Firefox, на F12 включаете инструменты разработчика. Заходите во вкладку сеть, там отображаются все запросы. Копируете нужный запрос как curl.

И вставляете в окно сайта curlconverter.com, язык выбираете Dart. И код запроса создастся автоматически.

Итоговый результат.

Пожалуйста отключи блокировщик рекламы, или внеси сайт в белый список!

Please disable your adblocker or whitelist this site!