From 3f258eb7bb257c709ddfdc262dfd1b787c39b005 Mon Sep 17 00:00:00 2001 From: unwox Date: Tue, 18 Feb 2025 12:31:18 +0600 Subject: add teaworkshop parser --- parser/daochai.fnl | 2 +- parser/parser.fnl | 10 ++++-- parser/teaworkshop.fnl | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 parser/teaworkshop.fnl (limited to 'parser') diff --git a/parser/daochai.fnl b/parser/daochai.fnl index 50ec508..e8f66a5 100644 --- a/parser/daochai.fnl +++ b/parser/daochai.fnl @@ -179,7 +179,7 @@ {:path "chay-i-chan/kurilnicy-i-podstavki-pod-blagovoniya" :tags ["Благовония"]} {:path "chay-i-chan/chetki" :tags ["Четки"]} {:path "chay-i-chan/dekorirovanie-prostranstva" :tags ["Декор"]} - {:path "chay-i-chan/figurki-iz-dereva" :tags ["Фигурки"]}] + {:path "chay-i-chan/figurki-iz-dereva" :tags ["Фигурка"]}] format-url product-peg normalize)) diff --git a/parser/parser.fnl b/parser/parser.fnl index afb1ae2..5cb64c3 100644 --- a/parser/parser.fnl +++ b/parser/parser.fnl @@ -158,7 +158,7 @@ (let [peg (peg.Ct (anywhere (* (peg.C pegs.number) - (maybe " ") + (maybe (+ (peg.P " ") " ")) (* (peg.C (if extra-metrics (+ (peg.P "гр") "кг" (table.unpack extra-metrics)) @@ -184,7 +184,7 @@ (let [peg (peg.Ct (anywhere (* (peg.C pegs.number) - (maybe " ") + (maybe (+ (peg.P " ") " ")) (* (peg.C (+ (peg.P "мл") "л")) (+ (pnot pegs.letter) -1)))))] (let [result (peg:match text)] @@ -194,6 +194,12 @@ nil))) nil)) +(fn test-guess-volume [] + (assert (= nil (guess-volume "Сервиз Хуа Хэ Няо"))) + (assert (= 255 (guess-volume "Бутылка для чая «Походная» 255 мл"))) + (assert (= 255 (guess-volume "Бутылка для чая «Походная» 255 мл")))) +(test-guess-volume) + {: match-many : tag : anywhere diff --git a/parser/teaworkshop.fnl b/parser/teaworkshop.fnl new file mode 100644 index 0000000..dcf2d78 --- /dev/null +++ b/parser/teaworkshop.fnl @@ -0,0 +1,92 @@ +(import-macros {: map} :lib.macro) + +(local fennel (require :vendor.fennel)) +(local parser (require :parser.parser)) +(local array (require :lib.array)) +(local http (require :lib.http)) +(local number (require :lib.number)) +(local fetcher (require :fetcher)) +(local json (require :vendor.json)) + +(fn format-url [path page] + (.. "https://api.teaworkshop.ru/shop-api/filters/popular/" path + "?limit=40&page=" page)) + +(fn destruct-response [response] + {:items (. (json.decode response) :items)}) + +(fn normalize [product] + (local image (?. product :images 1 :cachedPath)) + (var variant nil) + (var weight nil) + + ;; choosing a variant with parseable weight and tracked = 0 (meaning the + ;; variant is in stock) + (each [_ v (pairs product.variants) &until variant] + (when (= v.tracked 0) + (each [_ axis (pairs v.nameAxis) &until weight] + (set weight (parser.guess-weight axis ["г"])) + (when weight + (set variant v))))) + + ;; if there are no variants with parsable weight: choose the first one with + ;; tracked == 0 + (when (not variant) + (each [_ v (pairs product.variants) &until variant] + (when (= v.tracked 0) + (set variant v)))) + + (when variant + {:site "teaworkshop" + :url (.. "https://teaworkshop.ru/product/" product.slug) + :title product.name + :description nil + :image image + :weight weight + :volume (parser.guess-volume product.name) + :price (/ variant.price.current 100) + :price-per (if (and variant.price.current weight (< 0 weight)) + (/ (math.ceil (* (/ variant.price.current weight 100) 10)) 10) + nil)})) + +(fn products [] + (fetcher.from-json + [{:path "shu-pujer-chernyj" :tags ["Шу пуэр"]} + {:path "shen-puer" :tags ["Шен пуэр"]} + {:path "red" :tags ["Красный чай"]} + {:path "zheltyi-chai" :tags ["Желтый чай"]} + {:path "ansi" :tags ["Улун" "Фудзянь" "Аньси"]} + {:path "guandun" :tags ["Улун" "Гуандун"]} + {:path "tajvan" :tags ["Улун" "Тайвань"]} + {:path "uishan" :tags ["Улун" "Фудзянь" "Уишань"]} + {:path "ulun" :tags ["Улун"]} + {:path "green" :tags ["Зеленый чай"]} + {:path "white" :tags ["Белый чай"]} + {:path "hei-cha-chiornyi-chai" :tags ["Хэй ча"]} + {:path "nabori" :tags ["Набор"]} + {:path "avtorskii-chai" :tags ["Авторский чай"]} + {:path "gaba" :tags ["Габа"]} + {:path "tailand-tea" :tags ["Тайланд"]} + {:path "konkursnyi-chai" :tags ["Конкурсный чай"]} + {:path "krasnodar-chai" :tags ["Краснодар"]} + {:path "clay-teapot" :tags ["Посуда" "Чайник" "Исин"]} + {:path "chainiki-keramika-tszindechzhen" :tags ["Посуда" "Цзиндэчжэнь"]} + {:path "gaiwan" :tags ["Посуда" "Гайвань"]} + {:path "easy-teapot" :tags ["Посуда" "Типот"]} + {:path "cinchzhouskaja-keramika-nisin-tao" :tags ["Посуда" "Чайник" "Гуанси"]} + {:path "keramika-dehua" :tags ["Посуда" "Керамика" "Дэхуа"]} + {:path "czjanshujskaja-keramika" :tags ["Посуда" "Керамика" "Цзяньшуй"]} + {:path "chajniki-keramika" :tags ["Посуда" "Чайник"]} + {:path "glass-teapot" :tags ["Посуда" "Чайник" "Стекло"]} + {:path "chashki" :tags ["Посуда" "Пиала"]} + {:path "chaxaj-slivnik" :tags ["Посуда" "Чахай"]} + {:path "chabani" :tags ["Посуда" "Чабань"]} + {:path "prinadlezhnosti" :tags ["Аксессуар"]} + {:path "tea-spirit" :tags ["Фигурка"]} + {:path "banochki" :tags ["Посуда" "Чайница"]} + {:path "nabori-stuff" :tags ["Посуда" "Набор"]}] + format-url + destruct-response + normalize)) + +{:products products :title "Чайная мастерская" :url "https://teaworkshop.ru"} -- cgit v1.2.3