summaryrefslogtreecommitdiff
path: root/parser
diff options
context:
space:
mode:
authorunwox <me@unwox.com>2025-02-18 12:31:18 +0600
committerunwox <me@unwox.com>2025-02-18 12:31:18 +0600
commit3f258eb7bb257c709ddfdc262dfd1b787c39b005 (patch)
tree34ff3657aff04748345022a776ab0c972252d890 /parser
parent34a6a60c407c75e66f94b185aa6845621e4c49ed (diff)
add teaworkshop parser
Diffstat (limited to 'parser')
-rw-r--r--parser/daochai.fnl2
-rw-r--r--parser/parser.fnl10
-rw-r--r--parser/teaworkshop.fnl92
3 files changed, 101 insertions, 3 deletions
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 " ") "&nbsp;"))
(* (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 " ") "&nbsp;"))
(* (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&nbsp;мл"))))
+(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"}