Манипулируем объектами

Используем хеш-таблицы

Хеш-таблицы используются как словари для очень многих целей, например вы можете создать словарь уже посещенных страниц и перед переходом на страницу, проверять были ли вы уже на ней. Также можно создавать референсные наборы данных для дальнейшей популяции объектов с данными. Хеш-таблицы нельзя использовать как подставные данные, но вы можете читать значения в регистр и работать с ними дальше.

Команда hashmap_set используется для записи значения поля хеш-таблицы из регистра (только в блоковом контексте) или напрямую:

              # ПЕРЕХОДИМ В БЛОК
- find:
    path: .somepath
    do:
    - parse

    # ЗАПОЛНЯЕМ ЭЛЕМЕНТ ХЕШ-ТАБЛИЦЫ ЗНАЧЕНИЕМ РЕГИСТРА
    - hashmap_set:
        name: currency
        field: EUR

# ЗАПОЛНЯЕМ ЭЛЕМЕНТ ХЕШ-ТАБЛИЦЫ ЗАДАННЫМ ЗНАЧЕНИЕМ
- hashmap_set:
    name: currency
    field: USD
    value: United States Dollar
              

Команда hashmap_get используется для записи значения поля хеш-таблицы в регистр:

              # ПЕРЕХОДИМ В БЛОК
- find:
    path: .somepath
    do:
    # ЗАПОЛНЯЕМ РЕГИСТР ЗНАЧЕНИЕМ ЭЛЕМЕНТА ХЕШ-ТАБЛИЦЫ
    - hashmap_get:
        name: currency
        field: EUR
              

Давайте посмотрим как можно использовать хэш-таблицу для предотвращения сбора данных о мероприятиях, если регистрационный номер мероприятия дублируется. Исходный HTML для нашего сценария доступен по этой ссылке.
Обратите внимание, мероприятие за номером 363101-09 дублируется в таблице, а нам требуется забрать лишь первую встретившуюся запись и проигнорировать все последующие дубли идущие под этим же номером.

              ---
config:
    debug: 2
    agent: Firefox
do:
- walk:
    to: https://www.diggernaut.com/sandbox/meta-lang-hash-table-ru.html
    do:
    - find:
        # НАЙДЕМ ВСЕ ТЕГИ `tr`
        path: tbody > tr
        do:
        # ОЧИСТИМ ПЕРЕМЕННУЮ РЕГИСТРАЦИОННОГО НОМЕРА МЕРОПРИЯТИЯ
        - variable_clear: number
        - find:
            path: td.col2
            do:
            - parse
            # СОХРАНИМ РЕГ. НОМЕР В ПЕРЕМЕННУЮ
            - variable_set: number
        # ПРОБУЕМ НАЙТИ РЕГ. НОМЕР В ХЭШ-ТАБЛИЦЕ И ИЗВЛЕЧЬ ПОЛЕ `name`
        - hashmap_get:
            name: <%number%>
            field: name
        - if:
            # ЕСЛИ ПОЛЕ ЗАПОЛНЕНО ДАННЫМИ, ТО НИЧЕГО НЕ ДЕЛАЕМ
            match: \S
            # ЕСЛИ ПОЛЕ НЕ ЗАПОЛНЕНО ДАННЫМИ, ТО ЗАПИСЫВАЕМ ДАННЫЕ
            else:
            # СОЗДАЕМ НОВЫЙ ОБЪЕКТ `item`
            - object_new: item
            - find:
                path: td.col3
                do:
                - parse
                # СОХРАНЯЕМ РЕГ. НОМЕР В ХЭШ-ТАБЛИЦУ В ПОЛЕ `name` ДЛЯ
                # ПОСЛЕДУЮЩИХ ПРОВЕРОК ДУБЛИКАТОВ
                - hashmap_set:
                    name: <%number%>
                    field: name
                # СОХРАНЯЕМ В ОБЪЕКТ ИМЯ МЕРОПРИЯТИЯ
                - object_field_set:
                    object: item
                    field: name
            - find:
                path: td.col4
                do:
                - parse
                # СОХРАНЯЕМ В ОБЪЕКТ МЕСТО ПРОВЕДЕНИЯ
                - object_field_set:
                    object: item
                    field: location
            - find:
                path: td.col10
                do:
                - parse
                # СОХРАНЯЕМ В ОБЪЕКТ СТАТУС МЕРОПРИЯТИЯ
                - object_field_set:
                    object: item
                    field: isAvailable
            # СОХРАНЯЕМ ДАННЫЕ
            - object_save:
                name: item
              
              <!DOCTYPE html>
<html lang="ru">

<head>
    <meta charset="UTF-8">
    <title>Diggernaut | Мета-язык | Пример использования хеш-таблицы</title>
</head>

<body>
    <div class="result-content">
        <div>
            <h3>363101&nbsp;-&nbsp;Jr Golf Clinic Orange</h3>
        </div>
        <table cellspacing="2" border="1" cellpadding="5">
            <thead>
                <tr>
                    <th>Рег. номер</th>
                    <th>Описание</th>
                    <th>Место проведения</th>
                    <th>Статус</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td class="col2">
                        <span class="nowrap">363101-07</span>
                    </td>
                    <td class="col3">Jr Golf-Orange 4,5:31</td>
                    <td class="col4">Randall Oaks Golf Cl</td>
                    <td class="col10">
                        <span class="success arstatus">Available</span>
                    </td>
                </tr>
                <tr>
                    <td class="col2">
                        <span class="nowrap">363101-09</span>
                    </td>
                    <td class="col3">Jr Golf-Orange 4,5:30</td>
                    <td class="col4">Randall Oaks Golf Cl</td>
                    <td class="col10">
                        <span class="success arstatus">Available</span>
                    </td>
                </tr>
                <tr>
                    <td class="col2">
                        <span class="nowrap">363101-09</span>
                    </td>
                    <td class="col3">Jr Golf-Orange 5,5:30</td>
                    <td class="col4">Randall Oaks Golf Cl</td>
                    <td class="col10">
                        <span class="success arstatus">Available</span>
                    </td>
                </tr>
                <tr>
                    <td class="col2">
                        <span class="nowrap">363101-10</span>
                    </td>
                    <td class="col3">Jr Golf-Orange 5,6:23</td>
                    <td class="col4">Randall Oaks Golf Cl</td>
                    <td class="col10">
                        <span class="success arstatus">Available</span>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</body>
</html>
              
              [
    {
        "item": {
            "isAvailable": "Available",
            "location": "Randall Oaks Golf Cl",
            "name": "Jr Golf-Orange 4,5:31"
        }
    },
    {
        "item": {
            "isAvailable": "Available",
            "location": "Randall Oaks Golf Cl",
            "name": "Jr Golf-Orange 4,5:30"
        }
    },
    {
        "item": {
            "isAvailable": "Available",
            "location": "Randall Oaks Golf Cl",
            "name": "Jr Golf-Orange 5,6:23"
        }
    }
]
            

Далее мы рассмотрим насколько полезными могут быть счетчики и какие методы для них предусмотрены.