Сбор характеристик товара

Сбор характеристик товара

English Name
Collection of product characteristics
В этом уроке будет рассмотрен пример парсинга неизвестного количества характеристик товара.
Готовые пресеты можно посмотреть здесь

sstoc_200103092306.png


В качестве примера мы взяли сайт arcpalace.com.ua
Для того чтобы наш парсер не занял всю память, мы используем встроенную БД Sqlite для временного хранения данных.
Из-за некоторых ограничений А-Парсер'a пришлось разбить задание на 2 пресета которые объединены в цепочку.
Весь принцип работы данного пресета описан ниже.
Пресет 1:
  1. Парсим ссылки на товары.
Пресет 2:
  1. Используя файл результата из пресета 1 парсим информацию о товарах.
  2. Пишем всю информацию в БД.
  3. В конце задания выгружаем данные в .csv файл.

Пресет 1
4267k_191230124112.png

Думаю тут все понятно, в массив links заносим ссылки на товары и также реализована пагинация для перехода между страницами.
Для передачи файла результатов в пресет 2, используем опцию Запустить по завершению.
3ef0s_191230132123.png


Пресет 2
2in2a_191230132729.png

titile - название товара, features - характеристики, свойства (name - название характеристики, value значение), price - цена, code - артикул.

Для лучшего понимания рассмотрим сайт донор.
qzf0j_191230133457.png


Теперь разберем код в поле Формат результата.
Код:
[% CALL tools.sqlite.run(db, "CREATE TABLE IF NOT EXISTS products(code TEXT PRIMARY KEY, title TEXT, price INTEGER)");
CALL tools.sqlite.run(db, "CREATE TABLE IF NOT EXISTS columns(name TEXT PRIMARY KEY)");

row = tools.sqlite.get(db, "SELECT code FROM products WHERE code = ?", p1.code);
IF !row.0.code;
    CALL tools.sqlite.run(db, "INSERT INTO products(code, title, price) VALUES(?, ?, ?)", p1.code, p1.title, p1.price);
    FOREACH item IN p1.features;
        column = tools.sqlite.get(db, "SELECT COUNT(*) AS exist FROM pragma_table_info('products') WHERE name = ?", item.name);
        IF !column.0.exist;
            CALL tools.sqlite.run(db, "ALTER TABLE products add `" _ item.name _ "` TEXT");
            CALL tools.sqlite.run(db, "INSERT INTO columns(name) VALUES(?)", item.name);
        END;
        CALL tools.sqlite.run(db, "UPDATE products SET `" _ item.name _ "` = ? WHERE code = ?", item.value, p1.code);
    END;
END %]

Для работы с БД используем встроенные функции А-Парсер'a tools.sqlite.*
Код:
CALL tools.sqlite.run(db, "CREATE TABLE IF NOT EXISTS products(code TEXT PRIMARY KEY, title TEXT, price INTEGER)");
CALL tools.sqlite.run(db, "CREATE TABLE IF NOT EXISTS columns(name TEXT PRIMARY KEY)");
Создаем две таблицы products - информация о товарах, columns - уникальные название характеристик.
СALL - позволяет выполнить запрос, но не печатает возвращаемый результат.

Код:
row = tools.sqlite.get(db, "SELECT code FROM products WHERE code = ?", p1.code);
Проверяем есть ли такой товар в базе.

Код:
column = tools.sqlite.get(db, "SELECT COUNT(*) AS exist FROM pragma_table_info('products') WHERE name = ?", item.name);
Данная выборка позволяет проверить существует ли указанная колонка в таблице, в результате запроса будет 1 или 0.
pragma_table_info('products') - выводит все колонки из таблицы products.

Рассмотрим код в Конечном тексте, который выполняется в конце задания.
Код:
[%
cols = [];
FOREACH col IN tools.sqlite.all(db, "SELECT * FROM columns");
    cols.push(col.name);
END;
cols = cols.sort;
cols.unshift('title', 'price');
cols.join(';') _ "\n";

USE Math;
rows = tools.sqlite.get(db, "SELECT COUNT(*) AS count FROM products");
blockSize = 100;
blocksCount = Math.int(rows.count / blockSize + 0.999);

FOREACH b IN [1..blocksCount];
    block = tools.sqlite.all(db, "SELECT * FROM products WHERE rowid > ? AND rowid <= ?", (b - 1) * blockSize, b * blockSize);
    FOREACH row IN block;
        FOREACH col IN cols;
            row.${col} _ ';';
        END;
        "\n";
    END;
END %]

Код:
cols = cols.sort;
cols.unshift('title', 'price');
cols.join(';') _ "\n";
cols.sort - метод sort позволяет отсортировать элементы в массиве
Код:
list = [ 'c', 'b', 'a' ]
list.sort = >  [ 'a', 'b', 'c' ]
unshift() - добавляет элементы в начало массива, а push() - в конец массива.
join() - объединяет все элементы массива в строку, в качестве параметра указывается разделитель в нашем случае это точка с запятой.

Чтобы не выгружать весь результат сразу, так как это может съесть всю память, мы будем подгружать данные блоками.
Код:
rows = tools.sqlite.get(db, "SELECT COUNT(*) AS count FROM products");
blockSize = 100;
blocksCount = Math.int(rows.count / blockSize + 0.999);
В rows записываем общее количество товаров, blockSize - размер блока, blocksCount - количество блоков.
Например в rows получилось 1501 строк, Math.int(1501/100) = 15.01 => 15 так как целое число и меньше 0.5 тогда оно округляется в меньшую сторону, 15 * 100 = 1500 а строк 1501 получается что 1 строка пропадает нужно прибавить 0.999, Math.int(1501/ 100 + 0.999) = 16 * 100 = 1600 теперь все строки попадаю в заданный диапазон 1 - 1600;

Код:
FOREACH b IN [1..16];
    block = tools.sqlite.all(db, "SELECT * FROM products WHERE rowid > ? AND rowid <= ?", (1 - 1) * 100, 1 * 100);
После подстановки значений вместо переменных, можно увидеть процесс работы.






Автор
Support Alexander
Просмотры
45
Первый выпуск
Обновление

Рейтинги

0,00 звёзд Оценок: 0

Ещё ресурсы от Support Alexander

Назад
Верх