summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/fetch.fnl2
-rw-r--r--bin/serve.fnl10
-rw-r--r--parser/chaekshop.fnl88
-rw-r--r--static/chaekshop.svg3
4 files changed, 101 insertions, 2 deletions
diff --git a/bin/fetch.fnl b/bin/fetch.fnl
index c51d0f9..3dcaded 100644
--- a/bin/fetch.fnl
+++ b/bin/fetch.fnl
@@ -7,6 +7,7 @@
(local ipuer (require :parser.ipuer))
(local artoftea (require :parser.artoftea))
(local clubcha (require :parser.clubcha))
+(local chaekshop (require :parser.chaekshop))
(local db (luna.db.open "file:var/db.sqlite?_journal=WAL&_sync=NORMAL"))
(luna.db.exec db "
@@ -72,6 +73,7 @@
FROM products;" [])
(luna.db.commit tx))
+(store-products (chaekshop.products))
(store-products (clubcha.products))
(store-products (artoftea.products))
(store-products (ipuer.products))
diff --git a/bin/serve.fnl b/bin/serve.fnl
index eb56d8a..bec5a94 100644
--- a/bin/serve.fnl
+++ b/bin/serve.fnl
@@ -56,6 +56,11 @@
:alt "Логотип Железный Феникс"}
[:img {:src "/static/clubcha.png"}]
"Железный Феникс"]
+ (= name "chaekshop")
+ [:a {:class "site-icon" :href "https://chaekshop.ru"
+ :alt "Логотип Интернет-магазин фермерского китайского чая «Чаёк»"}
+ [:img {:src "/static/chaekshop.svg"}]
+ "Интернет-магазин «Чаёк»"]
""))
(fn item-template [product]
@@ -75,7 +80,8 @@
(< 0 product.price-per))
[:NO-ESCAPE (.. " (" product.price-per "₽ за&nbsp;1&nbsp;гр.)")]
"")]
- [:small {} (unescape (str.truncate product.description 200))]])
+ ;; FIXME: security issue
+ [:small {} [:NO-ESCAPE (unescape (str.truncate product.description 200))]]])
(fn paginator-template [query page limit total]
(local last-page (math.ceil (/ total limit)))
@@ -120,7 +126,7 @@
:alt "Логотип meicha.ru" :title "Логотип meicha.ru"}])
[:form {:class "form"}
[:input {:type :search :name :query :value query
- :autofocus true :placeholder "Введите поисковый запрос"}]
+ :autofocus true :placeholder "Поисковый запрос"}]
[:button {:type :submit} "Искать"]]
paginator]]
[:section {}
diff --git a/parser/chaekshop.fnl b/parser/chaekshop.fnl
new file mode 100644
index 0000000..b1e4b4e
--- /dev/null
+++ b/parser/chaekshop.fnl
@@ -0,0 +1,88 @@
+(import-macros {: map} :lib.macro)
+
+(local peg
+ (if (pick-values 1 (pcall require :lpeg))
+ (require :lpeg)
+ (require :lpeglj)))
+(local parser (require :parser.parser))
+(local number (require :lib.number))
+(local fetcher (require :fetcher))
+
+(fn format-url [path page]
+ (.. "https://chaekshop.ru/catalog/" path "?page=" page))
+
+(local data-v-peg
+ (* (peg.P "data-v-") (^ (+ parser.pegs.letters parser.pegs.number) 1)))
+
+(local product-peg
+ (*
+ (parser.anywhere
+ (parser.tag :a {data-v-peg "" :href (peg.Cg (parser.till "\"") :url)
+ :class "*" :itemprop "url" :section_id "*"}))
+ (parser.anywhere
+ (parser.tag :img {:src (peg.Cg (parser.till "\"") :image)
+ :alt "*"
+ :title (peg.Cg (parser.till "\"") :title)
+ :loading "lazy"
+ data-v-peg ""}))
+ (parser.anywhere
+ (parser.tag :p {:itemprop "price" :class "*" data-v-peg ""}
+ (* (peg.Cg (^ (+ parser.pegs.number " " ",") 1) :price) "₽")))
+ (parser.anywhere
+ (parser.tag :p {:class "*" data-v-peg ""}
+ (+ (* (peg.Cg parser.pegs.number :weight) " грамм")
+ (* parser.pegs.number " шт"))))))
+
+(fn normalize [product]
+ (local weight (or (number.string->number product.weight)
+ (parser.guess-weight product.title)))
+ (local price (number.string->number (string.gsub product.price "," ".")))
+ {:site "chaekshop"
+ :id (.. "https://chaekshop.ru/" product.url)
+ :title product.title
+ :url (.. "https://chaekshop.ru/" product.url)
+ :description ""
+ :image (.. "https://chaekshop.ru" product.image)
+ :year (parser.guess-year product.title)
+ :price price
+ :weight weight
+ :price-per (if (and price weight (< 0 weight))
+ (/ (math.ceil (* (/ price weight) 10)) 10)
+ nil)})
+
+(fn products []
+ (fetcher.from-html
+ [{:path "chay/belyy_chay" :category "Белый чай"}
+ {:path "chay/guandunskie_uluny" :category "Улун"}
+ {:path "chay/zhyeltyy_chay" :category "Желтый чай"}
+ {:path "chay/zelyenyy_chay" :category "Зеленый чай"}
+ {:path "chay/krasnyy_chay" :category "Красный чай"}
+ {:path "chay/severo_futszyanskie_uluny" :category "Улун"}
+ {:path "chay/tayvanskie_uluny" :category "Улун"}
+ {:path "chay/khey_cha" :category "Хэй ча"}
+ {:path "chay/shen_puer" :category "Шэн пуэр"}
+ {:path "chay/shu_puery" :category "Шу пуэр"}
+ {:path "chay/yuzhno_futszyanskie_uluny_" :category "Улун"}
+ {:path "chay/yunnanskie_uluny" :category "Улун"}
+ {:path "chay/gaba_chay" :category "Улун"}
+ {:path "chay/na_kazhdyy_den"}
+ {:path "chay/eksklyuziv"}
+ {:path "posuda_i_aksessuary/pialy" :category "Посуда"}
+ {:path "posuda_i_aksessuary/isinskaya_glina" :category "Посуда"}
+ {:path "posuda_i_aksessuary/keramika_iz_tszindechzhen" :category "Посуда"}
+ {:path "posuda_i_aksessuary/keramika_iz_tszyanshuy" :category "Посуда"}
+ {:path "posuda_i_aksessuary/kolby_termosy_nabory" :category "Посуда"}
+ {:path "posuda_i_aksessuary/chabani" :category "Посуда"}
+ {:path "posuda_i_aksessuary/chaynye_figurki" :category "Посуда"}
+ {:path "posuda_i_aksessuary/slivniki" :category "Посуда"}
+ {:path "posuda_i_aksessuary/gayvani" :category "Посуда"}
+ {:path "posuda_i_aksessuary/keramika_iz_tsinchzhou" :category "Посуда"}
+ {:path "posuda_i_aksessuary/aksessuary"}
+ {:path "posuda_i_aksessuary/pialy_tszindechzhen" :category "Посуда"}
+ {:path "posuda_i_aksessuary/keramika_dekhua" :category "Посуда"}
+ {:path "posuda_i_aksessuary/chayniki_iz_farfora" :category "Посуда"}]
+ format-url
+ product-peg
+ normalize))
+
+{: products}
diff --git a/static/chaekshop.svg b/static/chaekshop.svg
new file mode 100644
index 0000000..00146bd
--- /dev/null
+++ b/static/chaekshop.svg
@@ -0,0 +1,3 @@
+<svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M86.7327 48.8756L81.7889 39.3407H65.7517L54.3689 33L42.9861 39.2454H27.1901L21.0164 51.164L6.25731 40.8425L1 43.6076L14.5291 64.6797L3.79747 86.8246H109.764L110.752 82.7722L117.119 56.5512L117.264 55.9076L117.891 53.357L119 48.8518L86.7327 48.8756ZM54.3689 36.2657L59.795 39.2454H48.9428L54.3689 36.2657ZM19.4247 77.0513L33.0503 49.6861H75.5187L89.4337 77.0513H19.4247ZM103.445 81.342L90.7118 56.5751H110.174L103.445 81.342Z" fill="#65A30D"/>
+</svg>