diff --git a/analysis.js b/analysis.js
index 2a50af1..6cd71f9 100644
--- a/analysis.js
+++ b/analysis.js
@@ -285,7 +285,6 @@ exports.updateData = async function (dataDir, done) {
console.log("Fetching data for date: " + today);
const storeFetchPromises = [];
for (const store of STORE_KEYS) {
- if (store == "billa") continue;
storeFetchPromises.push(
new Promise(async (resolve) => {
const start = performance.now();
diff --git a/site/index.html b/site/index.html
index 1d92a2a..54411c8 100644
--- a/site/index.html
+++ b/site/index.html
@@ -9,9 +9,9 @@
__Medienberichte__
+
Achtung
- Die letzten Daten für Billa und Bipa stammen vom 15.10.2023 und werden derzeit nicht aktualisiert.
+ Die letzten Bipa stammen vom 15.10.2023 und werden derzeit nicht aktualisiert.
diff --git a/site/model/categories.js b/site/model/categories.js
index f8f3121..faf72d6 100644
--- a/site/model/categories.js
+++ b/site/model/categories.js
@@ -58,7 +58,7 @@ exports.categories = [
/*41*/ "Unbekannt", // Not available in Billa hierarchy, left blank
/*42*/ "Fertiggerichte",
/*43*/ "Fisch & Garnelen",
- /*44*/ "Gemüse & Kräuter",
+ /*44*/ "Gemüse, Kräuter & Obst",
/*45*/ "Pommes Frites & Co.",
/*46*/ "Pizza & Baguette",
/*47*/ "Desserts & Früchte",
diff --git a/site/model/stores.js b/site/model/stores.js
index d62ec3e..97bc379 100644
--- a/site/model/stores.js
+++ b/site/model/stores.js
@@ -6,7 +6,7 @@ exports.stores = {
budgetBrands: ["clever"],
color: "yellow",
defaultChecked: true,
- getUrl: (item) => `https://shop.billa.at/produkte/${item.id}`,
+ getUrl: (item) => `https://shop.billa.at/produkte/${item.url}`,
},
spar: {
name: "Spar",
diff --git a/stores/billa-new.js b/stores/billa-new.js
deleted file mode 100644
index 818f467..0000000
--- a/stores/billa-new.js
+++ /dev/null
@@ -1,101 +0,0 @@
-const axios = require("axios");
-const fs = require("fs");
-
-const baseCategorySlugs = [
- "obst-und-gemuese-13751",
- "brot-und-gebaeck-13766",
- "getraenke-13784",
- "kuehlwaren-13841",
- "tiefkuehl-13916",
- "nahrungsmittel-13943",
- "suesses-und-salziges-14057",
- "pflege-14083",
- "haushalt-14126",
- "haustier-14181",
-];
-
-// Map from old categories (see categories.js) to new categories in new Billa Store
-const subCategoryMap = {
- "vegan-13911": "3A",
- "tofu-14529": "3A",
- "fleisch-und-gefluegel-13921": "42",
- "fisch-und-meeresfruechte-13930": "43",
- "pizza-baguette-und-gebaeck-13936": "46",
- "pommes-frites-und-mehr-13935": "45",
- "tiefkuehlgerichte-13922": "42",
- "gemuese-kraeuter-und-obst-13934": "44",
- "eis-13917": "40",
- "suessspeisen-und-torten-13939": "47",
- "vegane-ernaehrung-14048": "5D",
- "filter-und-entkalker-14535": "88",
- "hygiene-schutzartikel-14536": "8F",
-};
-
-exports.generateCategories = async function () {
- const categories = [];
- let baseIndex = 0;
- for (const baseSlug of baseCategorySlugs) {
- const data = await axios.get(`https://shop.billa.at/api/categories/${baseSlug}/child-properties?storeId=00-10`);
- data.data.forEach((value, index) => {
- const code = subCategoryMap[value.slug] ?? baseIndex.toString(16).toUpperCase() + index.toString(16).toUpperCase();
- categories.push({
- id: value.slug,
- description: value.name,
- url: "https://shop.billa.at/kategorie/" + value.slug,
- code,
- });
- });
- baseIndex++;
- }
- return categories;
-};
-
-exports.fetchData = async function () {
- const categories = await exports.generateCategories();
- const rawItems = [];
- for (const category of categories) {
- let page = 0;
- while (true) {
- const data = await axios.get(`https://shop.billa.at/api/categories/${category.id}/products?pageSize=500&storeId=00-10&page=${page}`);
- page++;
- if (data.data.count == 0) break;
- for (const rawItem of data.data.results) {
- rawItem.mappedCategory = category.code;
- }
- rawItems.push(...data.data.results);
- }
- console.log("Fetched Billa category " + category.id);
- }
- const lookup = {};
- const dedupRawItems = [];
- let duplicates = 0;
- for (const rawItem of rawItems) {
- if (lookup[rawItem.sku]) {
- duplicates++;
- } else {
- lookup[rawItem.sku] = rawItem;
- dedupRawItems.push(rawItem);
- }
- }
- console.log("Billa duplicates: " + duplicates);
- console.log("Billa total items: " + dedupRawItems.length);
- return dedupRawItems;
-};
-
-if (require.main === module) {
- main();
-}
-
-async function main() {
- const oldItems = JSON.parse(fs.readFileSync("latest-canonical.json")).filter((item) => item.store == "billa");
- const oldItemsLookup = {};
- for (const oldItem of oldItems) {
- oldItemsLookup[oldItem.id] = oldItem;
- }
- const newItems = await exports.fetchData();
- for (const newItem of newItems) {
- if (!oldItemsLookup[newItem.sku]) {
- console.log("Couldn't find " + newItem.sku + " " + newItem.name);
- }
- }
-}
diff --git a/stores/billa.js b/stores/billa.js
index efac829..8b32546 100644
--- a/stores/billa.js
+++ b/stores/billa.js
@@ -1,77 +1,118 @@
const axios = require("axios");
+const fs = require("fs");
const utils = require("./utils");
-const { categories, toCategoryCode, fromCategoryCode, getCategory } = require("../site/model/categories");
-const HITS = Math.floor(30000 + Math.random() * 2000);
const units = {
beutel: { unit: "stk", factor: 1 },
bund: { unit: "stk", factor: 1 },
packung: { unit: "stk", factor: 1 },
+ pa: { unit: "stk", factor: 1 },
+ fl: { unit: "stk", factor: 1 },
portion: { unit: "stk", factor: 1 },
rollen: { unit: "stk", factor: 1 },
teebeutel: { unit: "stk", factor: 1 },
waschgang: { unit: "wg", factor: 1 },
};
+const baseCategorySlugs = [
+ "obst-und-gemuese-13751",
+ "brot-und-gebaeck-13766",
+ "getraenke-13784",
+ "kuehlwaren-13841",
+ "tiefkuehl-13916",
+ "nahrungsmittel-13943",
+ "suesses-und-salziges-14057",
+ "pflege-14083",
+ "haushalt-14126",
+ "haustier-14181",
+];
+
+// Map from old categories (see categories.js) to new categories in new Billa Store
+const subCategoryMap = {
+ "vegan-13911": "3A",
+ "tofu-14529": "3A",
+ "fleisch-und-gefluegel-13921": "42",
+ "fisch-und-meeresfruechte-13930": "43",
+ "pizza-baguette-und-gebaeck-13936": "46",
+ "pommes-frites-und-mehr-13935": "45",
+ "tiefkuehlgerichte-13922": "42",
+ "gemuese-kraeuter-und-obst-13934": "44",
+ "eis-13917": "40",
+ "suessspeisen-und-torten-13939": "47",
+ "vegane-ernaehrung-14048": "5D",
+ "filter-und-entkalker-14535": "83",
+ "hygiene-schutzartikel-14536": "8F",
+};
+
exports.getCanonical = function (item, today) {
- let quantity = 1,
- unit = "kg";
-
- if (item.data.grammagePriceFactor == 1) {
- if (item.data.grammage.indexOf("Per ") == 0) item.data.grammage = item.data.grammage.replace("Per ", "");
- const grammage = item.data.grammage !== "" && item.data.grammage.trim().split(" ").length > 1 ? item.data.grammage : item.data.price.unit;
- if (grammage) [quantity, unit] = grammage.trim().split(" ").splice(0, 2);
- }
-
+ const price = item.price.regular.value / 100;
return utils.convertUnit(
{
- id: item.data.articleId,
- name: item.data.name,
- description: item.data.description ?? "",
- price: item.data.price.final,
- priceHistory: [{ date: today, price: item.data.price.final }],
- isWeighted: item.data.isWeightArticle,
- unit,
- quantity,
- bio: item.data.attributes && item.data.attributes.includes("s_bio"),
+ id: item.sku,
+ name: item.name,
+ description: item.descriptionShort ?? "",
+ price,
+ priceHistory: [{ date: today, price }],
+ isWeighted: item.weightArticle,
+ unit: item.volumeLabelShort ?? item.price.baseUnitShort,
+ quantity: parseFloat(item.amount),
+ bio: item.badges && item.badges.includes("pp-bio") ? true : false,
+ url: item.slug,
},
units,
"billa"
);
};
-exports.fetchData = async function () {
- const items = [];
- const lookup = {};
- let numDuplicates = 0;
-
- for (let i = 1; i <= categories.length; i++) {
- const category = categories[i - 1];
- const categoryCode = i < 10 ? "" + i : String.fromCharCode("A".charCodeAt(0) + (i - 10));
-
- for (let j = 1; j <= category.subcategories.length; j++) {
- const subCategoryCode = j < 10 ? "" + j : String.fromCharCode("A".charCodeAt(0) + (j - 10));
- const code = `B2-${categoryCode}${subCategoryCode}`;
-
- const BILLA_SEARCH = `https://shop.billa.at/api/search/full?searchTerm=*&storeId=00-10&pageSize=${HITS}&category=${code}`;
- const data = (await axios.get(BILLA_SEARCH)).data;
- data.tiles.forEach((item) => {
- try {
- const canonicalItem = exports.getCanonical(item);
- if (lookup[canonicalItem.id]) {
- numDuplicates++;
- return;
- }
- lookup[canonicalItem.id] = item;
- items.push(item);
- } catch (e) {
- // Ignore super tiles
- }
+exports.generateCategories = async function () {
+ const categories = [];
+ let baseIndex = 0;
+ for (const baseSlug of baseCategorySlugs) {
+ const data = await axios.get(`https://shop.billa.at/api/categories/${baseSlug}/child-properties?storeId=00-10`);
+ data.data.forEach((value, index) => {
+ const code = subCategoryMap[value.slug] ?? baseIndex.toString(16).toUpperCase() + index.toString(16).toUpperCase();
+ categories.push({
+ id: value.slug,
+ description: value.name,
+ url: "https://shop.billa.at/kategorie/" + value.slug,
+ code,
});
+ });
+ baseIndex++;
+ }
+ return categories;
+};
+
+exports.fetchData = async function () {
+ const categories = await exports.generateCategories();
+ const rawItems = [];
+ for (const category of categories) {
+ let page = 0;
+ while (true) {
+ const data = await axios.get(`https://shop.billa.at/api/categories/${category.id}/products?pageSize=500&storeId=00-10&page=${page}`);
+ page++;
+ if (data.data.count == 0) break;
+ for (const rawItem of data.data.results) {
+ rawItem.mappedCategory = category.code;
+ }
+ rawItems.push(...data.data.results);
+ }
+ // console.log("Fetched Billa category " + category.id);
+ }
+ const lookup = {};
+ const dedupRawItems = [];
+ let duplicates = 0;
+ for (const rawItem of rawItems) {
+ if (lookup[rawItem.sku]) {
+ duplicates++;
+ } else {
+ lookup[rawItem.sku] = rawItem;
+ dedupRawItems.push(rawItem);
}
}
- console.log(`Duplicate items in BILLA data: ${numDuplicates}, total items: ${items.length}`);
- return items;
+ // console.log("Billa duplicates: " + duplicates);
+ // console.log("Billa total items: " + dedupRawItems.length);
+ return dedupRawItems;
};
exports.initializeCategoryMapping = async () => {
@@ -79,21 +120,91 @@ exports.initializeCategoryMapping = async () => {
};
exports.mapCategory = (rawItem) => {
- let billaCategory = null;
- for (const groupId of rawItem.data.articleGroupIds) {
- if (billaCategory == null) {
- billaCategory = groupId;
- continue;
- }
-
- if (groupId.charCodeAt(3) < billaCategory.charCodeAt(3)) {
- billaCategory = groupId;
- }
- }
- let categoryCode = billaCategory.replace("B2-", "").substring(0, 2);
- let [ci, cj] = fromCategoryCode(categoryCode);
- categoryCode = toCategoryCode(ci - 1, cj - 1);
- return categoryCode;
+ return rawItem.mappedCategory;
};
exports.urlBase = "https://shop.billa.at";
+
+if (require.main === module) {
+ main();
+}
+
+/* Test code, ensuring the data from the old Billa store is still compatible with the data from the new Billa store.
+ you can get an old latest-canonical.json from here:
+ https://marioslab.io/uploads/latest-canonical-2023-10-22.json
+*/
+function currentDate() {
+ const currentDate = new Date();
+ const year = currentDate.getFullYear();
+ const month = String(currentDate.getMonth() + 1).padStart(2, "0");
+ const day = String(currentDate.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+}
+
+async function main() {
+ const categories = await exports.generateCategories();
+ console.log(categories);
+ const oldCanonical = fs.existsSync("old-canonical.json")
+ ? JSON.parse(fs.readFileSync("old-canonical.json"))
+ : (await axios.get("https://heisse-preise.io/data/latest-canonical.json")).data;
+ fs.writeFileSync("old-canonical.json", JSON.stringify(oldCanonical, null, 2));
+ const oldItems = oldCanonical.filter((item) => item.store == "billa");
+ const oldItemsLookup = {};
+ for (const oldItem of oldItems) {
+ oldItemsLookup[oldItem.id] = oldItem;
+ }
+ const newItems = fs.existsSync("billa-new.json") ? JSON.parse(fs.readFileSync("billa-new.json")) : await exports.fetchData();
+ fs.writeFileSync("billa-new.json", JSON.stringify(newItems, null, 2));
+ const canonicalItems = [];
+ for (const newItem of newItems) {
+ const canonicalItem = exports.getCanonical(newItem, currentDate());
+ canonicalItems.push(canonicalItem);
+ const oldItem = oldItemsLookup[newItem.sku];
+ if (!oldItem) continue;
+
+ let change = false;
+
+ if (Math.abs(canonicalItem.price - oldItem.price) / oldItem.price > 1) {
+ console.log(
+ "Too big a price difference " +
+ canonicalItem.id +
+ " " +
+ canonicalItem.name +
+ ", old: " +
+ oldItem.price +
+ ", new: " +
+ canonicalItem.price
+ );
+ change = true;
+ }
+ if (canonicalItem.isWeighted != oldItem.isWeighted) {
+ console.log(
+ "!= isWeighted " + canonicalItem.id + " " + canonicalItem.name + ", old: " + oldItem.isWeighted + ", new: " + canonicalItem.isWeighted
+ );
+ change = true;
+ }
+ if (canonicalItem.unit != oldItem.unit) {
+ console.log("!= unit " + canonicalItem.id + " " + canonicalItem.name + ", old: " + oldItem.unit + ", new: " + canonicalItem.unit);
+ change = true;
+ }
+ if (canonicalItem.quantity != oldItem.quantity) {
+ console.log(
+ "!= quantity " + canonicalItem.id + " " + canonicalItem.name + ", old: " + oldItem.quantity + ", new: " + canonicalItem.quantity
+ );
+ change = true;
+ }
+ if (canonicalItem.bio != oldItem.bio) {
+ console.log("!= bio " + canonicalItem.id + " " + canonicalItem.name + ", old: " + oldItem.bio + ", new: " + canonicalItem.bio);
+ change = true;
+ }
+ if (canonicalItem.category != oldItem.category) {
+ console.log(
+ "!= category " + canonicalItem.id + " " + canonicalItem.name + ", old: " + oldItem.category + ", new: " + canonicalItem.category
+ );
+ change = true;
+ }
+ if (change) console.log("\n");
+ }
+
+ console.log("Canonical items");
+}
diff --git a/stores/mueller-categories.json b/stores/mueller-categories.json
index 93549ca..2e525de 100644
--- a/stores/mueller-categories.json
+++ b/stores/mueller-categories.json
@@ -2044,6 +2044,11 @@
"url": "https://www.mueller.at/drogerie/lebensmittel/suessigkeiten/gebaeck/",
"code": "64"
},
+ {
+ "id": "Drogerie/Lebensmittel/Süßigkeiten/Chips",
+ "url": "https://www.mueller.at/drogerie/lebensmittel/suessigkeiten/chips/",
+ "code": "63"
+ },
{
"id": "Drogerie/Lebensmittel/Süßigkeiten/Bonbons & Lutscher",
"url": "https://www.mueller.at/drogerie/lebensmittel/suessigkeiten/bonbons-lutscher/",
@@ -2664,6 +2669,31 @@
"url": "https://www.mueller.at/haushalt/kochen-backen/",
"code": null
},
+ {
+ "id": "Haushalt/Kochen & Backen/Weihnachtsbäckerei",
+ "url": "https://www.mueller.at/haushalt/kochen-backen/weihnachtsbaeckerei/",
+ "code": null
+ },
+ {
+ "id": "Haushalt/Kochen & Backen/Weihnachtsbäckerei/Ausstechformen",
+ "url": "https://www.mueller.at/haushalt/kochen-backen/weihnachtsbaeckerei/ausstechformen/",
+ "code": null
+ },
+ {
+ "id": "Haushalt/Kochen & Backen/Weihnachtsbäckerei/Backformen",
+ "url": "https://www.mueller.at/haushalt/kochen-backen/weihnachtsbaeckerei/backformen/",
+ "code": null
+ },
+ {
+ "id": "Haushalt/Kochen & Backen/Weihnachtsbäckerei/Backhelfer",
+ "url": "https://www.mueller.at/haushalt/kochen-backen/weihnachtsbaeckerei/backhelfer/",
+ "code": null
+ },
+ {
+ "id": "Haushalt/Kochen & Backen/Weihnachtsbäckerei/Gebäckdosen",
+ "url": "https://www.mueller.at/haushalt/kochen-backen/weihnachtsbaeckerei/gebaeckdosen/",
+ "code": null
+ },
{
"id": "Haushalt/Kochen & Backen/Aufbewahrung",
"url": "https://www.mueller.at/haushalt/kochen-backen/aufbewahrung/",
@@ -2759,11 +2789,6 @@
"url": "https://www.mueller.at/haushalt/kochen-backen/kuechenhelfer-textilien/spezialhelfer/",
"code": null
},
- {
- "id": "Haushalt/Kochen & Backen/Auflauf- & Backformen",
- "url": "https://www.mueller.at/haushalt/kochen-backen/auflauf-backformen/",
- "code": null
- },
{
"id": "Haushalt/Putzen & Reinigen",
"url": "https://www.mueller.at/haushalt/putzen-reinigen/",
@@ -3109,11 +3134,6 @@
"url": "https://www.mueller.at/tiershop/aktionen/",
"code": null
},
- {
- "id": "Tiershop/Aktionen/Aus dem Prospekt",
- "url": "https://www.mueller.at/tiershop/aktionen/aus-dem-prospekt/",
- "code": null
- },
{
"id": "Tiershop/Aktionen/Kühlmatten",
"url": "https://www.mueller.at/tiershop/aktionen/kuehlmatten/",
@@ -3124,6 +3144,16 @@
"url": "https://www.mueller.at/tiershop/aktionen/adventkalender-fuer-hunde-katzen/",
"code": null
},
+ {
+ "id": "Haushalt/Kochen & Backen/Auflauf- & Backformen",
+ "url": "https://www.mueller.at/haushalt/kochen-backen/auflauf-backformen/",
+ "code": null
+ },
+ {
+ "id": "Tiershop/Aktionen/Aus dem Prospekt",
+ "url": "https://www.mueller.at/tiershop/aktionen/aus-dem-prospekt/",
+ "code": null
+ },
{
"id": "Naturshop/Lebensmittel",
"url": "https://www.mueller.at/naturshop/lebensmittel/",
@@ -3284,11 +3314,6 @@
"url": "https://www.mueller.at/naturshop/lebensmittel/babynahrung/beikost/abendbreie/",
"code": "51"
},
- {
- "id": "Drogerie/Lebensmittel/Süßigkeiten/Chips",
- "url": "https://www.mueller.at/drogerie/lebensmittel/suessigkeiten/chips/",
- "code": "63"
- },
{
"id": "Haushalt/Wohnen & Dekorieren/Windlichter & Kerzen",
"url": "https://www.mueller.at/haushalt/wohnen-dekorieren/windlichter-kerzen/",
diff --git a/stores/penny-categories.json b/stores/penny-categories.json
index f39980f..6372390 100644
--- a/stores/penny-categories.json
+++ b/stores/penny-categories.json
@@ -105,20 +105,30 @@
"code": "33"
},
{
- "id": "Kühlwaren -> Wurst, Schinken & Speck",
- "url": "https://www.penny.at/kategorie/wurst-schinken-und-speck-13044",
- "code": "37"
+ "id": "Kühlwaren -> Blätterteig & Strudelteig",
+ "url": "https://www.penny.at/kategorie/blaetterteig-und-strudelteig-13043",
+ "code": "36"
},
{
"id": "Kühlwaren -> Fisch",
"url": "https://www.penny.at/kategorie/fisch-13045",
"code": "39"
},
+ {
+ "id": "Kühlwaren -> Wurst, Schinken & Speck",
+ "url": "https://www.penny.at/kategorie/wurst-schinken-und-speck-13044",
+ "code": "37"
+ },
{
"id": "Tiefkühl",
"url": "https://www.penny.at/kategorie/tiefkuehl-13047",
"code": "40"
},
+ {
+ "id": "Tiefkühl -> Desserts & Früchte",
+ "url": "https://www.penny.at/kategorie/desserts-und-fruechte-13054",
+ "code": "47"
+ },
{
"id": "Tiefkühl -> Fertiggerichte",
"url": "https://www.penny.at/kategorie/fertiggerichte-13049",
@@ -129,6 +139,11 @@
"url": "https://www.penny.at/kategorie/pizza-und-baguette-13053",
"code": "46"
},
+ {
+ "id": "Tiefkühl -> Fisch & Garnelen",
+ "url": "https://www.penny.at/kategorie/fisch-und-garnelen-13050",
+ "code": "43"
+ },
{
"id": "Tiefkühl -> Gemüse & Kräuter",
"url": "https://www.penny.at/kategorie/gemuese-und-kraeuter-13051",
@@ -139,16 +154,31 @@
"url": "https://www.penny.at/kategorie/grundnahrungsmittel-13055",
"code": "50"
},
+ {
+ "id": "Grundnahrungsmittel -> Fertiggerichte",
+ "url": "https://www.penny.at/kategorie/fertiggerichte-13059",
+ "code": "54"
+ },
{
"id": "Grundnahrungsmittel -> Essig & Öle",
"url": "https://www.penny.at/kategorie/essig-und-oele-13058",
"code": "53"
},
+ {
+ "id": "Grundnahrungsmittel -> Gewürze & Würzmittel",
+ "url": "https://www.penny.at/kategorie/gewuerze-und-wuerzmittel-13060",
+ "code": null
+ },
{
"id": "Grundnahrungsmittel -> Asia Produkte",
"url": "https://www.penny.at/kategorie/asia-produkte-13056",
"code": "50"
},
+ {
+ "id": "Grundnahrungsmittel -> Backen",
+ "url": "https://www.penny.at/kategorie/backen-13057",
+ "code": "52"
+ },
{
"id": "Grundnahrungsmittel -> Konserven & Sauerwaren",
"url": "https://www.penny.at/kategorie/konserven-und-sauerwaren-13062",
@@ -180,9 +210,14 @@
"code": "5C"
},
{
- "id": "Grundnahrungsmittel -> Spezielle Ernährung",
- "url": "https://www.penny.at/kategorie/spezielle-ernaehrung-13068",
- "code": "5D"
+ "id": "Grundnahrungsmittel -> Zucker & Süßstoffe",
+ "url": "https://www.penny.at/kategorie/zucker-und-suessstoffe-13069",
+ "code": "5E"
+ },
+ {
+ "id": "Grundnahrungsmittel -> Basisprodukte",
+ "url": "https://www.penny.at/kategorie/basisprodukte-13070",
+ "code": null
},
{
"id": "Süßes & Salziges",
@@ -190,13 +225,13 @@
"code": "60"
},
{
- "id": "Süßes & Salziges -> Süßwaren",
- "url": "https://www.penny.at/kategorie/suesswaren-13075",
+ "id": "Süßes & Salziges -> Schokolade",
+ "url": "https://www.penny.at/kategorie/schokolade-13074",
"code": "64"
},
{
- "id": "Süßes & Salziges -> Schokolade",
- "url": "https://www.penny.at/kategorie/schokolade-13074",
+ "id": "Süßes & Salziges -> Süßwaren",
+ "url": "https://www.penny.at/kategorie/suesswaren-13075",
"code": "64"
},
{
@@ -224,11 +259,6 @@
"url": "https://www.penny.at/kategorie/haushalt-13089",
"code": "80"
},
- {
- "id": "Haushalt -> Küchenrollen & WC-Papier",
- "url": "https://www.penny.at/kategorie/kuechenrollen-und-wcpapier-13094",
- "code": "84"
- },
{
"id": "Haushalt -> Waschmittel & Weichspüler",
"url": "https://www.penny.at/kategorie/waschmittel-und-weichspueler-13099",
@@ -239,11 +269,21 @@
"url": "https://www.penny.at/kategorie/reinigen-und-pflegen-13097",
"code": "88"
},
+ {
+ "id": "Haushalt -> Küchenrollen & WC-Papier",
+ "url": "https://www.penny.at/kategorie/kuechenrollen-und-wcpapier-13094",
+ "code": "84"
+ },
{
"id": "Haushalt -> Raumsprays & Kerzen",
"url": "https://www.penny.at/kategorie/raumsprays-und-kerzen-13096",
"code": null
},
+ {
+ "id": "Haushalt -> Müllsäcke, Gefrierbeutel & Co.",
+ "url": "https://www.penny.at/kategorie/muellsaecke-gefrierbeutel-und-co-13095",
+ "code": null
+ },
{
"id": "Haushalt -> Taschentücher & Servietten",
"url": "https://www.penny.at/kategorie/taschentuecher-und-servietten-13098",
@@ -275,38 +315,43 @@
"code": "73"
},
{
- "id": "Pflege -> Seifen & Duschbäder",
- "url": "https://www.penny.at/kategorie/seifen-und-duschbaeder-13085",
- "code": "78"
+ "id": "Pflege -> Damenhygiene",
+ "url": "https://www.penny.at/kategorie/damenhygiene-13078",
+ "code": null
},
{
"id": "Pflege -> Mund- & Zahnhygiene",
"url": "https://www.penny.at/kategorie/mund-und-zahnhygiene-13083",
"code": null
},
+ {
+ "id": "Pflege -> Seifen & Duschbäder",
+ "url": "https://www.penny.at/kategorie/seifen-und-duschbaeder-13085",
+ "code": "78"
+ },
{
"id": "Pflege -> Strumpfhosen & Socken",
"url": "https://www.penny.at/kategorie/strumpfhosen-und-socken-13086",
"code": "7C"
},
+ {
+ "id": "Pflege -> Rasierbedarf",
+ "url": "https://www.penny.at/kategorie/rasierbedarf-13084",
+ "code": null
+ },
{
"id": "Non-Food",
"url": "https://www.penny.at/kategorie/nonfood-13106",
"code": "80"
},
- {
- "id": "Non-Food -> Spiele, Bücher & Co.",
- "url": "https://www.penny.at/kategorie/spiele-buecher-und-co-13110",
- "code": "8E"
- },
{
"id": "Non-Food -> Haushalt",
"url": "https://www.penny.at/kategorie/haushalt-13109",
"code": "82"
},
{
- "id": "Non-Food -> Bekleidung & Textilien",
- "url": "https://www.penny.at/kategorie/bekleidung-und-textilien-13107",
+ "id": "Non-Food -> Körbe, Koffer & Co.",
+ "url": "https://www.penny.at/kategorie/koerbe-koffer-und-co-13112",
"code": null
},
{
@@ -314,46 +359,36 @@
"url": "https://www.penny.at/kategorie/saison-13111",
"code": null
},
+ {
+ "id": "Non-Food -> Bekleidung & Textilien",
+ "url": "https://www.penny.at/kategorie/bekleidung-und-textilien-13107",
+ "code": null
+ },
+ {
+ "id": "Non-Food -> Spiele, Bücher & Co.",
+ "url": "https://www.penny.at/kategorie/spiele-buecher-und-co-13110",
+ "code": "8E"
+ },
{
"id": "Non-Food -> Küche",
"url": "https://www.penny.at/kategorie/kueche-13108",
"code": "83"
},
+ {
+ "id": "Grundnahrungsmittel -> Spezielle Ernährung",
+ "url": "https://www.penny.at/kategorie/spezielle-ernaehrung-13068",
+ "code": "5D"
+ },
{
"id": "Kühlwaren -> Tofu & Vegetarische/Vegane Produkte",
"url": "https://www.penny.at/kategorie/tofu-und-vegetarischevegane-produkte-13046",
"code": "3B"
},
- {
- "id": "Tiefkühl -> Desserts & Früchte",
- "url": "https://www.penny.at/kategorie/desserts-und-fruechte-13054",
- "code": "47"
- },
{
"id": "Tiefkühl -> Eis",
"url": "https://www.penny.at/kategorie/eis-13048",
"code": "40"
},
- {
- "id": "Grundnahrungsmittel -> Gewürze & Würzmittel",
- "url": "https://www.penny.at/kategorie/gewuerze-und-wuerzmittel-13060",
- "code": null
- },
- {
- "id": "Grundnahrungsmittel -> Zucker & Süßstoffe",
- "url": "https://www.penny.at/kategorie/zucker-und-suessstoffe-13069",
- "code": "5E"
- },
- {
- "id": "Grundnahrungsmittel -> Basisprodukte",
- "url": "https://www.penny.at/kategorie/basisprodukte-13070",
- "code": null
- },
- {
- "id": "Grundnahrungsmittel -> Backen",
- "url": "https://www.penny.at/kategorie/backen-13057",
- "code": "52"
- },
{
"id": "Pflege -> Baby",
"url": "https://www.penny.at/kategorie/baby-13077",
@@ -364,31 +399,11 @@
"url": "https://www.penny.at/kategorie/sonnen-und-insektenschutzmittel-13088",
"code": "79"
},
- {
- "id": "Kühlwaren -> Blätterteig & Strudelteig",
- "url": "https://www.penny.at/kategorie/blaetterteig-und-strudelteig-13043",
- "code": "36"
- },
- {
- "id": "Tiefkühl -> Fisch & Garnelen",
- "url": "https://www.penny.at/kategorie/fisch-und-garnelen-13050",
- "code": "43"
- },
- {
- "id": "Grundnahrungsmittel -> Fertiggerichte",
- "url": "https://www.penny.at/kategorie/fertiggerichte-13059",
- "code": "54"
- },
{
"id": "Haushalt -> Lampen & Batterien",
"url": "https://www.penny.at/kategorie/lampen-und-batterien-13102",
"code": "85"
},
- {
- "id": "Non-Food -> Körbe, Koffer & Co.",
- "url": "https://www.penny.at/kategorie/koerbe-koffer-und-co-13112",
- "code": null
- },
{
"id": "Süßes & Salziges -> Müsliriegel",
"url": "https://www.penny.at/kategorie/muesliriegel-13072",
diff --git a/stores/unimarkt-categories.json b/stores/unimarkt-categories.json
index f94cd51..328a79e 100644
--- a/stores/unimarkt-categories.json
+++ b/stores/unimarkt-categories.json
@@ -623,6 +623,18 @@
"url": "https://shop.unimarkt.at/waffeln-waffelmischungen",
"code": "64"
},
+ {
+ "id": "lebkuchen",
+ "description": "Süßes & Snacks -> Lebkuchen & mehr",
+ "url": "https://shop.unimarkt.at/lebkuchen",
+ "code": null
+ },
+ {
+ "id": "suesses-zu-weihnachten",
+ "description": "",
+ "url": "https://shop.unimarkt.at/suesses-zu-weihnachten",
+ "code": null
+ },
{
"id": "bonbons",
"description": "Süßes & Snacks -> Bonbons & Kaugummis -> Bonbons",