На прошлом уроке мы изучили основы языков для верстки сайтов HTML и CSS и создали с помощью них таблицу. А сегодня мы научим нашего робота автоматически собирать спарсенные данные о госконтрактах в эту таблицу. Для этого мы будем использовать Python-библиотеку Jinja2.

Видео: Глеб Лиманский

Jinja2 — это шаблонитизатор, с помощью которого можно подставлять переменные из Python на страницы в браузере. В нашем случае это будут спарсенные данные о госконтрактах, которые мы подставим в нашу таблицу. Принцип работы Jinja2 похож на метод f-строк. Только переменные заключаются в двойные фигурные скобки, а не одинарные.

Давайте посмотрим, как это работает, на простом примере. Для начала установите бибилиотеку через команду в терминале pipenv install Jinja2. Затем нужно импортировать класс Template. Создааем шаблон приветствия: Hello и имя, которое будем в этот шаблон как раз подставлять. В переменную template кладем наш шаблон (получаем объект template, то есть экземпляр класса Template). Затем применяем к объекту template метод render(), который обрабатывает наш шаблон. Так Jinja2 подставляет значение аргумента name, которое мы указали — Harry — в указанное нами место в шаблоне. Получаем результат: Hello, Harry. А вот как бы мы записали это с помощью f-строки.

Метод render() обрабатывает шаблон, используя именованные аргументы, которые ему передаются (как в примере с именем), или используя словарь. Для нашего случая нам нужен список со десятью словарями, где каждый словарь содержит данные о контракте из топа-10 крупнейших за неделю. Создадим такой список с помощью функции get_top_contracts(). Внутри нее нам пригодится наша рекурсивная функция, которую мы писали на предыдущих уроках. Также необходимо прописать условие для случаев, когда данных о поставщике контракта нет (к сожалению, на госзакупках это стало часто происходить). И возвращает наша функция первые 10 госконтрактов (словарей). 

Перейдем к нашу HTML-коду, который мы написали на прошлом уроке: его нужно обновить и подготовить для работы с Jinja2. Во-первых, добавим количество столбцов и правильно их переименуем. Во-вторых, пропишем выражения Jinja2 (как мы указывали name в двойных фигурных скобках в начале урока). Так как у нас довольно большой объем данных, нам нужно использовать цикл для их обработки. Открываем цикл Дзиндзя с помощью синтаксиса этой библиотеки, где items это наш список со словарями. Цикл будет ходить по каждому элементу словаря и заполнять наши строки в таблице (каждая строка в таблице это один словарь). В конце закрываем этот цикл тоже по правилу Jinja2. 

Теперь создадим папку templates в нашем проекте robot в Visual studio code и положим туда наш обновленный HTML-код. А в нашем основном документе — main.py — напишем функцию create_message() для того, чтобы отрендерить шаблон. Вверху кода, где у нас все импорты, добавим:

from jinja2 import Template

from jinja2 import Environment, FileSystemLoader, select_autoescape

Функция create_message() на вход получает наш список со словарями. Теперь нужно дать понять Jinja2, где ей брать HTML-шаблон. FileSystemLoader находит нашу папку с шаблонами. В select_autoescape прописываем форматы. А в переменную template загружается шаблон из файла — table.html. Затем рендерим наш шаблон с помощью уже известного нам метода, указываем что items в коде HTML — это наш список со словарями (top_contracts). Теперь message — это переменная, в которой лежит таблица с собранными данными о госконтрактах. Запишем ее в новый HTML-файл, чтобы потом можно было посмотреть результат в браузере. Наша функция возвращает сообщение с информацией про контракты в табличном виде, чтобы в дальнейшем мы могли передать это сообщение по почте. 

Добавим в наш итог (result) из документации API Clearspending сортировку по убыванию цены (sort='-price') и применим две сегодняшние функции.

Теперь откроем файл с новой таблицей и посмотрим через расширение Live server на итоговую таблицу в браузере.

К сожалению, как мы видим, данные о всех поставщиках скрыты с госзакупок. Такую картину по крупных контарктам мы наблюдаем уже несколько месяцев. Реестр становится все более закрытым.