From 6c07aef68cba2c2cf6e18040d96f559ad77701ce Mon Sep 17 00:00:00 2001 From: Matthew Bloomfield Date: Mon, 30 Nov 2020 14:56:00 -0500 Subject: [PATCH 01/15] adding melskitchencafe, tasteofhome, therecipecritic --- scrapers/index.js | 3 ++ scrapers/melskitchencafe.js | 54 ++++++++++++++++++++++++++++++++++++ scrapers/tasteofhome.js | 52 +++++++++++++++++++++++++++++++++++ scrapers/therecipecritic.js | 55 +++++++++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+) create mode 100644 scrapers/melskitchencafe.js create mode 100644 scrapers/tasteofhome.js create mode 100644 scrapers/therecipecritic.js diff --git a/scrapers/index.js b/scrapers/index.js index c5d3ad8..b26e1ff 100644 --- a/scrapers/index.js +++ b/scrapers/index.js @@ -21,6 +21,7 @@ const domains = { foodnetwork: require("./foodnetwork"), gimmesomeoven: require("./gimmesomeoven"), kitchenstories: require("./kitchenstories"), + melskitchencafe: require("./melskitchencafe"), minimalistbaker: require("./minimalistbaker"), myrecipes: require("./myrecipes"), nomnompaleo: require("./nomnompaleo"), @@ -31,6 +32,8 @@ const domains = { simplyrecipes: require("./simplyrecipes"), smittenkitchen: require("./smittenkitchen"), tastesbetterfromscratch: require("./tastesbetterfromscratch"), + tasteofhome: require("./tasteofhome"), + therecipecritic: require("./therecipecritic"), thepioneerwoman: require("./thepioneerwoman"), therealfoodrds: require("./therealfoodrds"), thespruceeats: require("./thespruceeats"), diff --git a/scrapers/melskitchencafe.js b/scrapers/melskitchencafe.js new file mode 100644 index 0000000..08736a9 --- /dev/null +++ b/scrapers/melskitchencafe.js @@ -0,0 +1,54 @@ +const request = require("request"); +const cheerio = require("cheerio"); + +const RecipeSchema = require("../helpers/recipe-schema"); + +const epicurious = url => { + const Recipe = new RecipeSchema(); + return new Promise((resolve, reject) => { + if (!url.includes("melskitchencafe.com")) { + reject(new Error("url provided must include 'melskitchencafe.com'")); + } else { + request(url, (error, response, html) => { + if (!error && response.statusCode === 200) { + const $ = cheerio.load(html); + + Recipe.image = $(".mv-create-image").attr("data-pin-media"); + Recipe.name = $("header.mv-create-header") + .text() + .trim(); + + $("div.mv-create-ingredients ul li").each((i, el) => { + Recipe.ingredients.push($(el).text()); + }); + + $("div.mv-create-instructions ol li").each((i, el) => { + Recipe.instructions.push( + $(el) + .text() + .replace(/\s\s+/g, "") + ); + }); + + Recipe.time.prep = $(".mv-create-time-prep .mv-time-part").text(); + Recipe.time.total = $(".mv-create-time-total .mv-time-part").text(); + Recipe.servings = $(".mv-create-time-yield .mv-create-time-format").text(); + + if ( + !Recipe.name || + !Recipe.ingredients.length || + !Recipe.instructions.length + ) { + reject(new Error("No recipe found on page")); + } else { + resolve(Recipe); + } + } else { + reject(new Error("No recipe found on page")); + } + }); + } + }); +}; + +module.exports = epicurious; diff --git a/scrapers/tasteofhome.js b/scrapers/tasteofhome.js new file mode 100644 index 0000000..c9d137c --- /dev/null +++ b/scrapers/tasteofhome.js @@ -0,0 +1,52 @@ +const request = require("request"); +const cheerio = require("cheerio"); + +const RecipeSchema = require("../helpers/recipe-schema"); + +const epicurious = url => { + const Recipe = new RecipeSchema(); + return new Promise((resolve, reject) => { + if (!url.includes("tasteofhome.com/recipes")) { + reject(new Error("url provided must include 'tasteofhome.com/recipes'")); + } else { + request(url, (error, response, html) => { + if (!error && response.statusCode === 200) { + const $ = cheerio.load(html); + + Recipe.name = $("h1.recipe-title") + .text() + .trim(); + + $(".recipe-ingredients__list li").each((i, el) => { + Recipe.ingredients.push($(el).text()); + }); + + $(".recipe-directions__item").each((i, el) => { + Recipe.instructions.push( + $(el) + .text() + .replace(/\s\s+/g, "") + ); + }); + + Recipe.time.total = $(".recipe-time-yield__label-prep").text(); + Recipe.servings = $(".recipe-time-yield__label-servings").text(); + + if ( + !Recipe.name || + !Recipe.ingredients.length || + !Recipe.instructions.length + ) { + reject(new Error("No recipe found on page")); + } else { + resolve(Recipe); + } + } else { + reject(new Error("No recipe found on page")); + } + }); + } + }); +}; + +module.exports = epicurious; diff --git a/scrapers/therecipecritic.js b/scrapers/therecipecritic.js new file mode 100644 index 0000000..5920ccb --- /dev/null +++ b/scrapers/therecipecritic.js @@ -0,0 +1,55 @@ +const request = require("request"); +const cheerio = require("cheerio"); + +const RecipeSchema = require("../helpers/recipe-schema"); + +const epicurious = url => { + const Recipe = new RecipeSchema(); + return new Promise((resolve, reject) => { + if (!url.includes("therecipecritic.com")) { + reject(new Error("url provided must include 'therecipecritic.com'")); + } else { + request(url, (error, response, html) => { + if (!error && response.statusCode === 200) { + const $ = cheerio.load(html); + + Recipe.image = $(".wprm-recipe-image img").attr("src"); + Recipe.name = $(".wprm-recipe-name") + .text() + .trim(); + + $(".wprm-recipe-ingredient").each((i, el) => { + Recipe.ingredients.push($(el).text()); + }); + + $(".wprm-recipe-instruction-text").each((i, el) => { + Recipe.instructions.push( + $(el) + .text() + .replace(/\s\s+/g, "") + ); + }); + + Recipe.time.total = $(".recipe-time-yield__label-prep").text(); + Recipe.time.prep = $(".wprm-recipe-prep_time").text() + ' ' + $(".wprm-recipe-prep_timeunit-minutes").text(); + Recipe.time.total = $(".wprm-recipe-total_time").text() + ' ' + $(".wprm-recipe-total_timeunit-minutes").text(); + Recipe.servings = $(".wprm-recipe-servings").text(); + ' ' + $(".wprm-recipe-servings-unit").text() + + if ( + !Recipe.name || + !Recipe.ingredients.length || + !Recipe.instructions.length + ) { + reject(new Error("No recipe found on page")); + } else { + resolve(Recipe); + } + } else { + reject(new Error("No recipe found on page")); + } + }); + } + }); +}; + +module.exports = epicurious; From b5ffe5ba077408701d190139ed4d85817e760d58 Mon Sep 17 00:00:00 2001 From: Matthew Bloomfield Date: Mon, 30 Nov 2020 16:00:50 -0500 Subject: [PATCH 02/15] Updating title field --- scrapers/melskitchencafe.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scrapers/melskitchencafe.js b/scrapers/melskitchencafe.js index 08736a9..dc8d5a9 100644 --- a/scrapers/melskitchencafe.js +++ b/scrapers/melskitchencafe.js @@ -14,7 +14,7 @@ const epicurious = url => { const $ = cheerio.load(html); Recipe.image = $(".mv-create-image").attr("data-pin-media"); - Recipe.name = $("header.mv-create-header") + Recipe.name = $(".mv-create-title-primary") .text() .trim(); From 7eeb4eed42de5bfd70cb82771f4128aa88930d7b Mon Sep 17 00:00:00 2001 From: Matthew Bloomfield Date: Mon, 30 Nov 2020 16:11:16 -0500 Subject: [PATCH 03/15] Update selector for name (two visible selectors) --- scrapers/melskitchencafe.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scrapers/melskitchencafe.js b/scrapers/melskitchencafe.js index dc8d5a9..99c3c80 100644 --- a/scrapers/melskitchencafe.js +++ b/scrapers/melskitchencafe.js @@ -15,6 +15,7 @@ const epicurious = url => { Recipe.image = $(".mv-create-image").attr("data-pin-media"); Recipe.name = $(".mv-create-title-primary") + .eq(0) .text() .trim(); From f31a46e419edc32d1996472cfa96f97c7126fea2 Mon Sep 17 00:00:00 2001 From: Matthew Bloomfield Date: Mon, 30 Nov 2020 17:28:03 -0500 Subject: [PATCH 04/15] Adding julieblanner.com --- scrapers/index.js | 1 + scrapers/julieblanner.js | 57 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 scrapers/julieblanner.js diff --git a/scrapers/index.js b/scrapers/index.js index b26e1ff..b621aed 100644 --- a/scrapers/index.js +++ b/scrapers/index.js @@ -20,6 +20,7 @@ const domains = { foodandwine: require("./foodandwine"), foodnetwork: require("./foodnetwork"), gimmesomeoven: require("./gimmesomeoven"), + julieblanner: require("./julieblanner"), kitchenstories: require("./kitchenstories"), melskitchencafe: require("./melskitchencafe"), minimalistbaker: require("./minimalistbaker"), diff --git a/scrapers/julieblanner.js b/scrapers/julieblanner.js new file mode 100644 index 0000000..2c401f8 --- /dev/null +++ b/scrapers/julieblanner.js @@ -0,0 +1,57 @@ +const request = require("request"); +const cheerio = require("cheerio"); + +const RecipeSchema = require("../helpers/recipe-schema"); + +const epicurious = url => { + const Recipe = new RecipeSchema(); + return new Promise((resolve, reject) => { + if (!url.includes("julieblanner.com")) { + reject(new Error("url provided must include 'julieblanner.com'")); + } else { + request(url, (error, response, html) => { + if (!error && response.statusCode === 200) { + const $ = cheerio.load(html); + + Recipe.image = $(".wprm-recipe-image img").attr("data-pin-media"); + Recipe.name = $(".wprm-recipe-name").eq(0) + .text() + .trim(); + + $('.wprm-recipe-ingredients > .wprm-recipe-ingredient') + .each((i, el) => { + Recipe.ingredients.push($(el).text().replace(/▢/g, '')); + }); + + $(".wprm-recipe-instruction-text").each((i, el) => { + Recipe.instructions.push( + $(el) + .remove('img') + .text() + .replace(/\s\s+/g, "") + ); + }); + + Recipe.time.prep = $(".wprm-recipe-prep_time-minutes").text() + ' ' + $(".wprm-recipe-prep_timeunit-minutes").text(); + Recipe.time.cook = $(".wprm-recipe-cook_time-minutes").text() + ' ' + $(".wprm-recipe-cook_timeunit-minutes").text(); + Recipe.time.total = $(".wprm-recipe-total_time-minutes").text() + ' ' + $(".wprm-recipe-total_timeunit-minutes").text(); + Recipe.servings = $(".wprm-recipe-servings").text(); + + if ( + !Recipe.name || + !Recipe.ingredients.length || + !Recipe.instructions.length + ) { + reject(new Error("No recipe found on page")); + } else { + resolve(Recipe); + } + } else { + reject(new Error("No recipe found on page")); + } + }); + } + }); +}; + +module.exports = epicurious; From 7f3326559990c05bf2a78c090565f3a222761f71 Mon Sep 17 00:00:00 2001 From: Matthew Bloomfield Date: Tue, 1 Dec 2020 10:30:15 -0500 Subject: [PATCH 05/15] Adding a few more... --- scrapers/gimmedelicious.js | 59 ++++++++++++++++++++++++++++++++++ scrapers/index.js | 2 ++ scrapers/julieblanner.js | 4 +-- scrapers/melskitchencafe.js | 4 +-- scrapers/tasteofhome.js | 4 +-- scrapers/theblackpeppercorn.js | 57 ++++++++++++++++++++++++++++++++ scrapers/therecipecritic.js | 4 +-- 7 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 scrapers/gimmedelicious.js create mode 100644 scrapers/theblackpeppercorn.js diff --git a/scrapers/gimmedelicious.js b/scrapers/gimmedelicious.js new file mode 100644 index 0000000..5f66e6d --- /dev/null +++ b/scrapers/gimmedelicious.js @@ -0,0 +1,59 @@ +const request = require("request"); +const cheerio = require("cheerio"); + +const RecipeSchema = require("../helpers/recipe-schema"); + +const gimmedelicious = url => { + const Recipe = new RecipeSchema(); + return new Promise((resolve, reject) => { + if (!url.includes("gimmedelicious.com")) { + reject(new Error("url provided must include 'gimmedelicious.com'")); + } else { + request(url, (error, response, html) => { + if (!error && response.statusCode === 200) { + const $ = cheerio.load(html); + + Recipe.image = $(".wprm-recipe-image img").attr("src"); + Recipe.name = $(".wprm-recipe-name").eq(0) + .text() + .trim(); + + $('.wprm-recipe-ingredients > .wprm-recipe-ingredient') + .each((i, el) => { + Recipe.ingredients.push($(el).text().replace(/▢/g, '')); + }); + + $(".wprm-recipe-instruction-text").each((i, el) => { + Recipe.instructions.push( + $(el) + .remove('img') + .text() + .replace(/\s\s+/g, "") + ); + }); + + Recipe.time.prep = $(".wprm-recipe-prep_time-minutes").text() + ' ' + $(".wprm-recipe-prep_timeunit-minutes").text(); + Recipe.time.cook = $(".wprm-recipe-cook_time-minutes").text() + ' ' + $(".wprm-recipe-cook_timeunit-minutes").text(); + Recipe.time.total = $(".wprm-recipe-total_time-minutes").text() + ' ' + $(".wprm-recipe-total_timeunit-minutes").text(); + Recipe.servings = $(".wprm-recipe-servings").text(); + + console.log('Recipe', JSON.stringify(Recipe)); + + if ( + !Recipe.name || + !Recipe.ingredients.length || + !Recipe.instructions.length + ) { + reject(new Error("No recipe found on page")); + } else { + resolve(Recipe); + } + } else { + reject(new Error("No recipe found on page")); + } + }); + } + }); +}; + +module.exports = gimmedelicious; diff --git a/scrapers/index.js b/scrapers/index.js index b621aed..9be5c15 100644 --- a/scrapers/index.js +++ b/scrapers/index.js @@ -19,6 +19,7 @@ const domains = { food: require("./food"), foodandwine: require("./foodandwine"), foodnetwork: require("./foodnetwork"), + gimmedelicious: require("./gimmedelicious"), gimmesomeoven: require("./gimmesomeoven"), julieblanner: require("./julieblanner"), kitchenstories: require("./kitchenstories"), @@ -34,6 +35,7 @@ const domains = { smittenkitchen: require("./smittenkitchen"), tastesbetterfromscratch: require("./tastesbetterfromscratch"), tasteofhome: require("./tasteofhome"), + theblackpeppercorn: require("./theblackpeppercorn"), therecipecritic: require("./therecipecritic"), thepioneerwoman: require("./thepioneerwoman"), therealfoodrds: require("./therealfoodrds"), diff --git a/scrapers/julieblanner.js b/scrapers/julieblanner.js index 2c401f8..03e8f6a 100644 --- a/scrapers/julieblanner.js +++ b/scrapers/julieblanner.js @@ -3,7 +3,7 @@ const cheerio = require("cheerio"); const RecipeSchema = require("../helpers/recipe-schema"); -const epicurious = url => { +const julieblanner = url => { const Recipe = new RecipeSchema(); return new Promise((resolve, reject) => { if (!url.includes("julieblanner.com")) { @@ -54,4 +54,4 @@ const epicurious = url => { }); }; -module.exports = epicurious; +module.exports = julieblanner; diff --git a/scrapers/melskitchencafe.js b/scrapers/melskitchencafe.js index 99c3c80..fdb5d7f 100644 --- a/scrapers/melskitchencafe.js +++ b/scrapers/melskitchencafe.js @@ -3,7 +3,7 @@ const cheerio = require("cheerio"); const RecipeSchema = require("../helpers/recipe-schema"); -const epicurious = url => { +const melskitchencafe = url => { const Recipe = new RecipeSchema(); return new Promise((resolve, reject) => { if (!url.includes("melskitchencafe.com")) { @@ -52,4 +52,4 @@ const epicurious = url => { }); }; -module.exports = epicurious; +module.exports = melskitchencafe; diff --git a/scrapers/tasteofhome.js b/scrapers/tasteofhome.js index c9d137c..d1e890e 100644 --- a/scrapers/tasteofhome.js +++ b/scrapers/tasteofhome.js @@ -3,7 +3,7 @@ const cheerio = require("cheerio"); const RecipeSchema = require("../helpers/recipe-schema"); -const epicurious = url => { +const tasteofhome = url => { const Recipe = new RecipeSchema(); return new Promise((resolve, reject) => { if (!url.includes("tasteofhome.com/recipes")) { @@ -49,4 +49,4 @@ const epicurious = url => { }); }; -module.exports = epicurious; +module.exports = tasteofhome; diff --git a/scrapers/theblackpeppercorn.js b/scrapers/theblackpeppercorn.js new file mode 100644 index 0000000..7ef3fa3 --- /dev/null +++ b/scrapers/theblackpeppercorn.js @@ -0,0 +1,57 @@ +const request = require("request"); +const cheerio = require("cheerio"); + +const RecipeSchema = require("../helpers/recipe-schema"); + +const theblackpeppercorn = url => { + const Recipe = new RecipeSchema(); + return new Promise((resolve, reject) => { + if (!url.includes("theblackpeppercorn.com")) { + reject(new Error("url provided must include 'theblackpeppercorn.com'")); + } else { + request(url, (error, response, html) => { + if (!error && response.statusCode === 200) { + const $ = cheerio.load(html); + + Recipe.image = $(".wprm-recipe-image img").attr("data-pin-media"); + Recipe.name = $(".wprm-recipe-name").eq(0) + .text() + .trim(); + + $('.wprm-recipe-ingredients > .wprm-recipe-ingredient') + .each((i, el) => { + Recipe.ingredients.push($(el).text().replace(/▢/g, '')); + }); + + $(".wprm-recipe-instruction-text").each((i, el) => { + Recipe.instructions.push( + $(el) + .remove('img') + .text() + .replace(/\s\s+/g, "") + ); + }); + + Recipe.time.prep = $(".wprm-recipe-prep_time-minutes").text() + ' ' + $(".wprm-recipe-prep_timeunit-minutes").text(); + Recipe.time.cook = $(".wprm-recipe-cook_time-minutes").text() + ' ' + $(".wprm-recipe-cook_timeunit-minutes").text(); + Recipe.time.total = $(".wprm-recipe-total_time-minutes").text() + ' ' + $(".wprm-recipe-total_timeunit-minutes").text(); + Recipe.servings = $(".wprm-recipe-servings").text(); + + if ( + !Recipe.name || + !Recipe.ingredients.length || + !Recipe.instructions.length + ) { + reject(new Error("No recipe found on page")); + } else { + resolve(Recipe); + } + } else { + reject(new Error("No recipe found on page")); + } + }); + } + }); +}; + +module.exports = theblackpeppercorn; diff --git a/scrapers/therecipecritic.js b/scrapers/therecipecritic.js index 5920ccb..2bbc618 100644 --- a/scrapers/therecipecritic.js +++ b/scrapers/therecipecritic.js @@ -3,7 +3,7 @@ const cheerio = require("cheerio"); const RecipeSchema = require("../helpers/recipe-schema"); -const epicurious = url => { +const therecipecritic = url => { const Recipe = new RecipeSchema(); return new Promise((resolve, reject) => { if (!url.includes("therecipecritic.com")) { @@ -52,4 +52,4 @@ const epicurious = url => { }); }; -module.exports = epicurious; +module.exports = therecipecritic; From 8b8dce202b647d1a33c2d6fdfa0fe221618c3f28 Mon Sep 17 00:00:00 2001 From: jadkins89 Date: Wed, 6 Jan 2021 12:14:29 -0700 Subject: [PATCH 06/15] minor gimmedelicious updates --- scrapers/gimmedelicious.js | 42 ++++++++++++++++++++++++++------------ scrapers/index.js | 4 ++++ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/scrapers/gimmedelicious.js b/scrapers/gimmedelicious.js index 5f66e6d..a9a06a7 100644 --- a/scrapers/gimmedelicious.js +++ b/scrapers/gimmedelicious.js @@ -13,32 +13,48 @@ const gimmedelicious = url => { if (!error && response.statusCode === 200) { const $ = cheerio.load(html); - Recipe.image = $(".wprm-recipe-image img").attr("src"); - Recipe.name = $(".wprm-recipe-name").eq(0) + Recipe.image = $("meta[property='og:image']").attr("content"); + Recipe.tags = $("meta[name='keywords']") + .attr("content") + .split(","); + Recipe.name = $(".wprm-recipe-name") + .eq(0) .text() .trim(); - $('.wprm-recipe-ingredients > .wprm-recipe-ingredient') - .each((i, el) => { - Recipe.ingredients.push($(el).text().replace(/▢/g, '')); - }); + $(".wprm-recipe-ingredients > .wprm-recipe-ingredient").each( + (i, el) => { + Recipe.ingredients.push( + $(el) + .text() + .replace(/▢/g, "") + ); + } + ); $(".wprm-recipe-instruction-text").each((i, el) => { Recipe.instructions.push( $(el) - .remove('img') + .remove("img") .text() - .replace(/\s\s+/g, "") + .trim() ); }); - Recipe.time.prep = $(".wprm-recipe-prep_time-minutes").text() + ' ' + $(".wprm-recipe-prep_timeunit-minutes").text(); - Recipe.time.cook = $(".wprm-recipe-cook_time-minutes").text() + ' ' + $(".wprm-recipe-cook_timeunit-minutes").text(); - Recipe.time.total = $(".wprm-recipe-total_time-minutes").text() + ' ' + $(".wprm-recipe-total_timeunit-minutes").text(); + Recipe.time.prep = + $(".wprm-recipe-prep_time-minutes").text() + + " " + + $(".wprm-recipe-prep_timeunit-minutes").text(); + Recipe.time.cook = + $(".wprm-recipe-cook_time-minutes").text() + + " " + + $(".wprm-recipe-cook_timeunit-minutes").text(); + Recipe.time.total = + $(".wprm-recipe-total_time-minutes").text() + + " " + + $(".wprm-recipe-total_timeunit-minutes").text(); Recipe.servings = $(".wprm-recipe-servings").text(); - console.log('Recipe', JSON.stringify(Recipe)); - if ( !Recipe.name || !Recipe.ingredients.length || diff --git a/scrapers/index.js b/scrapers/index.js index 9be5c15..c05c464 100644 --- a/scrapers/index.js +++ b/scrapers/index.js @@ -61,4 +61,8 @@ const recipeScraper = url => { }); }; +recipeScraper( + "https://gimmedelicious.com/creamy-spinach-and-mushroom-pasta-bake" +).then(recipe => console.log(recipe)); + module.exports = recipeScraper; From 06f2b927845ae2cb513b89bcf39458ef475e36b9 Mon Sep 17 00:00:00 2001 From: jadkins89 Date: Wed, 6 Jan 2021 12:32:56 -0700 Subject: [PATCH 07/15] minor melskitchencafe updates --- scrapers/index.js | 2 +- scrapers/melskitchencafe.js | 37 +++++++++++++++++++++++-------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/scrapers/index.js b/scrapers/index.js index c05c464..a0a3013 100644 --- a/scrapers/index.js +++ b/scrapers/index.js @@ -62,7 +62,7 @@ const recipeScraper = url => { }; recipeScraper( - "https://gimmedelicious.com/creamy-spinach-and-mushroom-pasta-bake" + "https://www.melskitchencafe.com/bbq-pulled-pork-sandwiches-slow-cooker/" ).then(recipe => console.log(recipe)); module.exports = recipeScraper; diff --git a/scrapers/melskitchencafe.js b/scrapers/melskitchencafe.js index fdb5d7f..e407eac 100644 --- a/scrapers/melskitchencafe.js +++ b/scrapers/melskitchencafe.js @@ -13,27 +13,36 @@ const melskitchencafe = url => { if (!error && response.statusCode === 200) { const $ = cheerio.load(html); - Recipe.image = $(".mv-create-image").attr("data-pin-media"); - Recipe.name = $(".mv-create-title-primary") - .eq(0) - .text() - .trim(); + const textTrim = el => el.text().trim(); + + Recipe.image = $("meta[property='og:image']").attr("content"); + Recipe.name = textTrim( + $(".wp-block-mv-recipe .mv-create-title-primary") + ); $("div.mv-create-ingredients ul li").each((i, el) => { - Recipe.ingredients.push($(el).text()); + Recipe.ingredients.push(textTrim($(el))); }); $("div.mv-create-instructions ol li").each((i, el) => { - Recipe.instructions.push( - $(el) - .text() - .replace(/\s\s+/g, "") - ); + Recipe.instructions.push(textTrim($(el))); }); - Recipe.time.prep = $(".mv-create-time-prep .mv-time-part").text(); - Recipe.time.total = $(".mv-create-time-total .mv-time-part").text(); - Recipe.servings = $(".mv-create-time-yield .mv-create-time-format").text(); + Recipe.time.prep = textTrim( + $(".mv-create-time-prep .mv-create-time-format") + ); + Recipe.time.cook = textTrim( + $(".mv-create-time-active .mv-create-time-format") + ); + Recipe.time.inactive = textTrim( + $(".mv-create-time-additional .mv-create-time-format") + ); + Recipe.time.total = textTrim( + $(".mv-create-time-total .mv-create-time-format") + ); + Recipe.servings = textTrim( + $(".mv-create-time-yield .mv-create-time-format") + ); if ( !Recipe.name || From 8d7ca7cac467269a7b87b0e1395dc087e440e271 Mon Sep 17 00:00:00 2001 From: jadkins89 Date: Wed, 6 Jan 2021 12:34:38 -0700 Subject: [PATCH 08/15] minor melskitchencafe updates --- scrapers/index.js | 6 +++--- scrapers/julieblanner.js | 34 +++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/scrapers/index.js b/scrapers/index.js index a0a3013..c981eb8 100644 --- a/scrapers/index.js +++ b/scrapers/index.js @@ -61,8 +61,8 @@ const recipeScraper = url => { }); }; -recipeScraper( - "https://www.melskitchencafe.com/bbq-pulled-pork-sandwiches-slow-cooker/" -).then(recipe => console.log(recipe)); +recipeScraper("https://julieblanner.com/cheese-ball-bites/").then(recipe => + console.log(recipe) +); module.exports = recipeScraper; diff --git a/scrapers/julieblanner.js b/scrapers/julieblanner.js index 03e8f6a..82b0085 100644 --- a/scrapers/julieblanner.js +++ b/scrapers/julieblanner.js @@ -12,29 +12,45 @@ const julieblanner = url => { request(url, (error, response, html) => { if (!error && response.statusCode === 200) { const $ = cheerio.load(html); + const textTrim = el => el.text().trim(); Recipe.image = $(".wprm-recipe-image img").attr("data-pin-media"); - Recipe.name = $(".wprm-recipe-name").eq(0) + Recipe.name = $(".wprm-recipe-name") + .eq(0) .text() .trim(); - $('.wprm-recipe-ingredients > .wprm-recipe-ingredient') - .each((i, el) => { - Recipe.ingredients.push($(el).text().replace(/▢/g, '')); - }); + $(".wprm-recipe-ingredients > .wprm-recipe-ingredient").each( + (i, el) => { + Recipe.ingredients.push( + $(el) + .text() + .replace(/▢/g, "") + ); + } + ); $(".wprm-recipe-instruction-text").each((i, el) => { Recipe.instructions.push( $(el) - .remove('img') + .remove("img") .text() .replace(/\s\s+/g, "") ); }); - Recipe.time.prep = $(".wprm-recipe-prep_time-minutes").text() + ' ' + $(".wprm-recipe-prep_timeunit-minutes").text(); - Recipe.time.cook = $(".wprm-recipe-cook_time-minutes").text() + ' ' + $(".wprm-recipe-cook_timeunit-minutes").text(); - Recipe.time.total = $(".wprm-recipe-total_time-minutes").text() + ' ' + $(".wprm-recipe-total_timeunit-minutes").text(); + Recipe.time.prep = + $(".wprm-recipe-prep_time-minutes").text() + + " " + + $(".wprm-recipe-prep_timeunit-minutes").text(); + Recipe.time.cook = + $(".wprm-recipe-cook_time-minutes").text() + + " " + + $(".wprm-recipe-cook_timeunit-minutes").text(); + Recipe.time.total = + $(".wprm-recipe-total_time-minutes").text() + + " " + + $(".wprm-recipe-total_timeunit-minutes").text(); Recipe.servings = $(".wprm-recipe-servings").text(); if ( From 85eadfc812a22ccfbd290a410aebc3d19a5eb03a Mon Sep 17 00:00:00 2001 From: jadkins89 Date: Wed, 6 Jan 2021 12:53:58 -0700 Subject: [PATCH 09/15] minor julieblanner updates --- scrapers/index.js | 6 +++--- scrapers/julieblanner.js | 33 ++++++++++++++++----------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/scrapers/index.js b/scrapers/index.js index c981eb8..e0e5e93 100644 --- a/scrapers/index.js +++ b/scrapers/index.js @@ -61,8 +61,8 @@ const recipeScraper = url => { }); }; -recipeScraper("https://julieblanner.com/cheese-ball-bites/").then(recipe => - console.log(recipe) -); +recipeScraper( + "https://julieblanner.com/reindeer-bacon-cheddar-cheeseball/" +).then(recipe => console.log(recipe)); module.exports = recipeScraper; diff --git a/scrapers/julieblanner.js b/scrapers/julieblanner.js index 82b0085..3efbbf1 100644 --- a/scrapers/julieblanner.js +++ b/scrapers/julieblanner.js @@ -12,11 +12,9 @@ const julieblanner = url => { request(url, (error, response, html) => { if (!error && response.statusCode === 200) { const $ = cheerio.load(html); - const textTrim = el => el.text().trim(); - Recipe.image = $(".wprm-recipe-image img").attr("data-pin-media"); + Recipe.image = $("meta[property='og:image']").attr("content"); Recipe.name = $(".wprm-recipe-name") - .eq(0) .text() .trim(); @@ -25,7 +23,8 @@ const julieblanner = url => { Recipe.ingredients.push( $(el) .text() - .replace(/▢/g, "") + .replace(/(\s\s+|▢)/g, " ") + .trim() ); } ); @@ -35,22 +34,22 @@ const julieblanner = url => { $(el) .remove("img") .text() - .replace(/\s\s+/g, "") + .trim() ); }); - Recipe.time.prep = - $(".wprm-recipe-prep_time-minutes").text() + - " " + - $(".wprm-recipe-prep_timeunit-minutes").text(); - Recipe.time.cook = - $(".wprm-recipe-cook_time-minutes").text() + - " " + - $(".wprm-recipe-cook_timeunit-minutes").text(); - Recipe.time.total = - $(".wprm-recipe-total_time-minutes").text() + - " " + - $(".wprm-recipe-total_timeunit-minutes").text(); + Recipe.time.prep = $(".wprm-recipe-prep-time-label") + .next() + .text(); + Recipe.time.cook = $(".wprm-recipe-cook-time-label") + .next() + .text(); + Recipe.time.inactive = $(".wprm-recipe-custom-time-label") + .next() + .text(); + Recipe.time.total = $(".wprm-recipe-total-time-label") + .next() + .text(); Recipe.servings = $(".wprm-recipe-servings").text(); if ( From 2aa7628840e2370a6a9399d53de942047d0ec373 Mon Sep 17 00:00:00 2001 From: jadkins89 Date: Wed, 6 Jan 2021 13:17:07 -0700 Subject: [PATCH 10/15] minor tweaks tasteofhome --- scrapers/index.js | 2 +- scrapers/tasteofhome.js | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/scrapers/index.js b/scrapers/index.js index e0e5e93..f08e570 100644 --- a/scrapers/index.js +++ b/scrapers/index.js @@ -62,7 +62,7 @@ const recipeScraper = url => { }; recipeScraper( - "https://julieblanner.com/reindeer-bacon-cheddar-cheeseball/" + "https://www.tasteofhome.com/recipes/beef-noodle-casserole/" ).then(recipe => console.log(recipe)); module.exports = recipeScraper; diff --git a/scrapers/tasteofhome.js b/scrapers/tasteofhome.js index d1e890e..8f7545e 100644 --- a/scrapers/tasteofhome.js +++ b/scrapers/tasteofhome.js @@ -13,10 +13,15 @@ const tasteofhome = url => { if (!error && response.statusCode === 200) { const $ = cheerio.load(html); + Recipe.image = $("meta[property='og:image']").attr("content"); Recipe.name = $("h1.recipe-title") .text() .trim(); + $("meta[property='article:tag']").each((i, el) => { + Recipe.tags.push($(el).attr("content")); + }); + $(".recipe-ingredients__list li").each((i, el) => { Recipe.ingredients.push($(el).text()); }); @@ -25,12 +30,18 @@ const tasteofhome = url => { Recipe.instructions.push( $(el) .text() - .replace(/\s\s+/g, "") + .trim() ); }); - Recipe.time.total = $(".recipe-time-yield__label-prep").text(); - Recipe.servings = $(".recipe-time-yield__label-servings").text(); + let timeStr = $(".recipe-time-yield__label-prep") + .text() + .split(/Bake:/g); + Recipe.time.prep = timeStr[0].replace("Prep:", "").trim(); + Recipe.time.cook = timeStr[1].trim(); + Recipe.servings = $(".recipe-time-yield__label-servings") + .text() + .trim(); if ( !Recipe.name || From 8ba5ccdb0f8d442d3cdf1c13536cdb97542059b4 Mon Sep 17 00:00:00 2001 From: jadkins89 Date: Wed, 6 Jan 2021 13:29:56 -0700 Subject: [PATCH 11/15] removing dev code --- scrapers/index.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scrapers/index.js b/scrapers/index.js index f08e570..9be5c15 100644 --- a/scrapers/index.js +++ b/scrapers/index.js @@ -61,8 +61,4 @@ const recipeScraper = url => { }); }; -recipeScraper( - "https://www.tasteofhome.com/recipes/beef-noodle-casserole/" -).then(recipe => console.log(recipe)); - module.exports = recipeScraper; From 39f55621619ab16960ef844b9269d510d6a4d37d Mon Sep 17 00:00:00 2001 From: jadkins89 Date: Wed, 6 Jan 2021 16:09:08 -0700 Subject: [PATCH 12/15] minor updates to theblackpeppercorn --- scrapers/theblackpeppercorn.js | 36 ++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/scrapers/theblackpeppercorn.js b/scrapers/theblackpeppercorn.js index 7ef3fa3..e2cc00b 100644 --- a/scrapers/theblackpeppercorn.js +++ b/scrapers/theblackpeppercorn.js @@ -13,28 +13,44 @@ const theblackpeppercorn = url => { if (!error && response.statusCode === 200) { const $ = cheerio.load(html); - Recipe.image = $(".wprm-recipe-image img").attr("data-pin-media"); - Recipe.name = $(".wprm-recipe-name").eq(0) + Recipe.image = $("meta[property='og:image']").attr("content"); + Recipe.name = $(".wprm-recipe-name") + .eq(0) .text() .trim(); - $('.wprm-recipe-ingredients > .wprm-recipe-ingredient') - .each((i, el) => { - Recipe.ingredients.push($(el).text().replace(/▢/g, '')); - }); + $(".wprm-recipe-ingredients > .wprm-recipe-ingredient").each( + (i, el) => { + Recipe.ingredients.push( + $(el) + .text() + .replace(/(▢)/g, "") + .replace(" ,", ",") + ); + } + ); $(".wprm-recipe-instruction-text").each((i, el) => { Recipe.instructions.push( $(el) - .remove('img') + .remove("img") .text() .replace(/\s\s+/g, "") ); }); - Recipe.time.prep = $(".wprm-recipe-prep_time-minutes").text() + ' ' + $(".wprm-recipe-prep_timeunit-minutes").text(); - Recipe.time.cook = $(".wprm-recipe-cook_time-minutes").text() + ' ' + $(".wprm-recipe-cook_timeunit-minutes").text(); - Recipe.time.total = $(".wprm-recipe-total_time-minutes").text() + ' ' + $(".wprm-recipe-total_timeunit-minutes").text(); + Recipe.time.prep = $(".wprm-recipe-prep-time-label") + .next() + .text(); + Recipe.time.cook = $(".wprm-recipe-cook-time-label") + .next() + .text(); + Recipe.time.inactive = $(".wprm-recipe-custom-time-label") + .next() + .text(); + Recipe.time.total = $(".wprm-recipe-total-time-label") + .next() + .text(); Recipe.servings = $(".wprm-recipe-servings").text(); if ( From 438734bf66b74169f1db1c8d3ecb07b1a15c5194 Mon Sep 17 00:00:00 2001 From: jadkins89 Date: Wed, 6 Jan 2021 16:29:16 -0700 Subject: [PATCH 13/15] minor updates to therecipecritic --- scrapers/theblackpeppercorn.js | 1 - scrapers/therecipecritic.js | 30 ++++++++++++++++-------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/scrapers/theblackpeppercorn.js b/scrapers/theblackpeppercorn.js index e2cc00b..97e7f7d 100644 --- a/scrapers/theblackpeppercorn.js +++ b/scrapers/theblackpeppercorn.js @@ -15,7 +15,6 @@ const theblackpeppercorn = url => { Recipe.image = $("meta[property='og:image']").attr("content"); Recipe.name = $(".wprm-recipe-name") - .eq(0) .text() .trim(); diff --git a/scrapers/therecipecritic.js b/scrapers/therecipecritic.js index 2bbc618..46000ea 100644 --- a/scrapers/therecipecritic.js +++ b/scrapers/therecipecritic.js @@ -12,28 +12,30 @@ const therecipecritic = url => { request(url, (error, response, html) => { if (!error && response.statusCode === 200) { const $ = cheerio.load(html); + const textTrim = el => el.text().trim(); - Recipe.image = $(".wprm-recipe-image img").attr("src"); - Recipe.name = $(".wprm-recipe-name") - .text() - .trim(); + Recipe.image = $("meta[property='og:image']").attr("content"); + Recipe.name = textTrim($(".wprm-recipe-name")); $(".wprm-recipe-ingredient").each((i, el) => { - Recipe.ingredients.push($(el).text()); + Recipe.ingredients.push(textTrim($(el)).replace(/\s\s+/g, " ")); }); $(".wprm-recipe-instruction-text").each((i, el) => { - Recipe.instructions.push( - $(el) - .text() - .replace(/\s\s+/g, "") - ); + Recipe.instructions.push(textTrim($(el)).replace(/\s\s+/g, " ")); }); - Recipe.time.total = $(".recipe-time-yield__label-prep").text(); - Recipe.time.prep = $(".wprm-recipe-prep_time").text() + ' ' + $(".wprm-recipe-prep_timeunit-minutes").text(); - Recipe.time.total = $(".wprm-recipe-total_time").text() + ' ' + $(".wprm-recipe-total_timeunit-minutes").text(); - Recipe.servings = $(".wprm-recipe-servings").text(); + ' ' + $(".wprm-recipe-servings-unit").text() + $(".wprm-recipe-details-name").remove(); + + Recipe.time.prep = textTrim($(".wprm-recipe-prep-time-container")); + Recipe.time.cook = textTrim($(".wprm-recipe-cook-time-container")); + Recipe.time.inactive = textTrim( + $(".wprm-recipe-custom-time-container") + ); + Recipe.time.total = textTrim($(".wprm-recipe-total-time-container")); + Recipe.servings = $( + ".wprm-recipe-servings-container .wprm-recipe-servings" + ).text(); if ( !Recipe.name || From db6f88a8ddcbf7ca1d9b3ba1ab9a2c70dfe2a856 Mon Sep 17 00:00:00 2001 From: jadkins89 Date: Wed, 6 Jan 2021 17:14:48 -0700 Subject: [PATCH 14/15] unit tests / misc updates / readme --- README.md | 5 ++ scrapers/gimmedelicious.js | 11 ++-- scrapers/index.js | 4 ++ scrapers/julieblanner.js | 4 +- scrapers/melskitchencafe.js | 4 +- scrapers/tasteofhome.js | 6 +- scrapers/theblackpeppercorn.js | 4 +- scrapers/therecipecritic.js | 4 +- scrapers/thespruceeats.js | 18 ++++-- test/constants/eatingwellConstants.js | 2 +- test/constants/gimmedeliciousConstants.js | 44 +++++++++++++ test/constants/julieblannerConstants.js | 42 ++++++++++++ test/constants/melskitchencafeConstants.js | 37 +++++++++++ test/constants/tasteofhomeConstants.js | 64 +++++++++++++++++++ test/constants/theblackpeppercornConstants.js | 42 ++++++++++++ test/constants/therecipecriticConstants.js | 35 ++++++++++ test/gimmedelicious.test.js | 11 ++++ test/julieblanner.test.js | 6 ++ test/melskitchencafe.test.js | 11 ++++ test/tasteofhome.test.js | 11 ++++ test/theblackpeppercorn.test.js | 11 ++++ test/therecipecritic.test.js | 11 ++++ 22 files changed, 363 insertions(+), 24 deletions(-) create mode 100644 test/constants/gimmedeliciousConstants.js create mode 100644 test/constants/julieblannerConstants.js create mode 100644 test/constants/melskitchencafeConstants.js create mode 100644 test/constants/tasteofhomeConstants.js create mode 100644 test/constants/theblackpeppercornConstants.js create mode 100644 test/constants/therecipecriticConstants.js create mode 100644 test/gimmedelicious.test.js create mode 100644 test/julieblanner.test.js create mode 100644 test/melskitchencafe.test.js create mode 100644 test/tasteofhome.test.js create mode 100644 test/theblackpeppercorn.test.js create mode 100644 test/therecipecritic.test.js diff --git a/README.md b/README.md index ba79d2f..ed70de1 100644 --- a/README.md +++ b/README.md @@ -52,8 +52,11 @@ recipeScraper("some.recipe.url").then(recipe => { - https://www.food.com/ - https://www.foodandwine.com/ - https://www.foodnetwork.com/ +- https://gimmedelicious.com/ - http://www.gimmesomeoven.com/ +- https://julieblanner.com/ - https://www.kitchenstories.com/ +- https://www.melskitchencafe.com/ - https://www.minimalistbaker.com/ - https://www.myrecipes.com/ - https://www.nomnompaleo.com/ @@ -64,7 +67,9 @@ recipeScraper("some.recipe.url").then(recipe => { - https://www.simplyrecipes.com/ - https://smittenkitchen.com/ - https://thepioneerwoman.com/ +- https://www.tasteofhome.com/ - https://tastesbetterfromscratch.com/ +- https://www.theblackpeppercorn.com/ - https://therealfoodrds.com/ - https://www.thespruceeats.com/ - https://whatsgabycooking.com/ diff --git a/scrapers/gimmedelicious.js b/scrapers/gimmedelicious.js index a9a06a7..7cb777c 100644 --- a/scrapers/gimmedelicious.js +++ b/scrapers/gimmedelicious.js @@ -6,19 +6,18 @@ const RecipeSchema = require("../helpers/recipe-schema"); const gimmedelicious = url => { const Recipe = new RecipeSchema(); return new Promise((resolve, reject) => { - if (!url.includes("gimmedelicious.com")) { - reject(new Error("url provided must include 'gimmedelicious.com'")); + if (!url.includes("gimmedelicious.com/")) { + reject(new Error("url provided must include 'gimmedelicious.com/'")); } else { request(url, (error, response, html) => { if (!error && response.statusCode === 200) { const $ = cheerio.load(html); Recipe.image = $("meta[property='og:image']").attr("content"); - Recipe.tags = $("meta[name='keywords']") - .attr("content") - .split(","); + Recipe.tags = ( + $("meta[name='keywords']").attr("content") || "" + ).split(","); Recipe.name = $(".wprm-recipe-name") - .eq(0) .text() .trim(); diff --git a/scrapers/index.js b/scrapers/index.js index 9be5c15..4cc9951 100644 --- a/scrapers/index.js +++ b/scrapers/index.js @@ -61,4 +61,8 @@ const recipeScraper = url => { }); }; +recipeScraper( + "https://www.thespruceeats.com/grilled-squid-recipe-1808848" +).then(recipe => console.log(recipe)); + module.exports = recipeScraper; diff --git a/scrapers/julieblanner.js b/scrapers/julieblanner.js index 3efbbf1..70a9fbd 100644 --- a/scrapers/julieblanner.js +++ b/scrapers/julieblanner.js @@ -6,8 +6,8 @@ const RecipeSchema = require("../helpers/recipe-schema"); const julieblanner = url => { const Recipe = new RecipeSchema(); return new Promise((resolve, reject) => { - if (!url.includes("julieblanner.com")) { - reject(new Error("url provided must include 'julieblanner.com'")); + if (!url.includes("julieblanner.com/")) { + reject(new Error("url provided must include 'julieblanner.com/'")); } else { request(url, (error, response, html) => { if (!error && response.statusCode === 200) { diff --git a/scrapers/melskitchencafe.js b/scrapers/melskitchencafe.js index e407eac..1a2e439 100644 --- a/scrapers/melskitchencafe.js +++ b/scrapers/melskitchencafe.js @@ -6,8 +6,8 @@ const RecipeSchema = require("../helpers/recipe-schema"); const melskitchencafe = url => { const Recipe = new RecipeSchema(); return new Promise((resolve, reject) => { - if (!url.includes("melskitchencafe.com")) { - reject(new Error("url provided must include 'melskitchencafe.com'")); + if (!url.includes("melskitchencafe.com/")) { + reject(new Error("url provided must include 'melskitchencafe.com/'")); } else { request(url, (error, response, html) => { if (!error && response.statusCode === 200) { diff --git a/scrapers/tasteofhome.js b/scrapers/tasteofhome.js index 8f7545e..36fa1d5 100644 --- a/scrapers/tasteofhome.js +++ b/scrapers/tasteofhome.js @@ -6,8 +6,8 @@ const RecipeSchema = require("../helpers/recipe-schema"); const tasteofhome = url => { const Recipe = new RecipeSchema(); return new Promise((resolve, reject) => { - if (!url.includes("tasteofhome.com/recipes")) { - reject(new Error("url provided must include 'tasteofhome.com/recipes'")); + if (!url.includes("tasteofhome.com/recipes/")) { + reject(new Error("url provided must include 'tasteofhome.com/recipes/'")); } else { request(url, (error, response, html) => { if (!error && response.statusCode === 200) { @@ -38,7 +38,7 @@ const tasteofhome = url => { .text() .split(/Bake:/g); Recipe.time.prep = timeStr[0].replace("Prep:", "").trim(); - Recipe.time.cook = timeStr[1].trim(); + Recipe.time.cook = (timeStr[1] || "").trim(); Recipe.servings = $(".recipe-time-yield__label-servings") .text() .trim(); diff --git a/scrapers/theblackpeppercorn.js b/scrapers/theblackpeppercorn.js index 97e7f7d..ac1c291 100644 --- a/scrapers/theblackpeppercorn.js +++ b/scrapers/theblackpeppercorn.js @@ -6,8 +6,8 @@ const RecipeSchema = require("../helpers/recipe-schema"); const theblackpeppercorn = url => { const Recipe = new RecipeSchema(); return new Promise((resolve, reject) => { - if (!url.includes("theblackpeppercorn.com")) { - reject(new Error("url provided must include 'theblackpeppercorn.com'")); + if (!url.includes("theblackpeppercorn.com/")) { + reject(new Error("url provided must include 'theblackpeppercorn.com/'")); } else { request(url, (error, response, html) => { if (!error && response.statusCode === 200) { diff --git a/scrapers/therecipecritic.js b/scrapers/therecipecritic.js index 46000ea..8156de7 100644 --- a/scrapers/therecipecritic.js +++ b/scrapers/therecipecritic.js @@ -6,8 +6,8 @@ const RecipeSchema = require("../helpers/recipe-schema"); const therecipecritic = url => { const Recipe = new RecipeSchema(); return new Promise((resolve, reject) => { - if (!url.includes("therecipecritic.com")) { - reject(new Error("url provided must include 'therecipecritic.com'")); + if (!url.includes("therecipecritic.com/")) { + reject(new Error("url provided must include 'therecipecritic.com/'")); } else { request(url, (error, response, html) => { if (!error && response.statusCode === 200) { diff --git a/scrapers/thespruceeats.js b/scrapers/thespruceeats.js index 5591213..425a2c8 100644 --- a/scrapers/thespruceeats.js +++ b/scrapers/thespruceeats.js @@ -43,12 +43,18 @@ const theSpruceEats = url => { ); }); - let metaText = $(".meta-text__data"); - Recipe.time.total = metaText.first().text(); - Recipe.time.prep = $(metaText.get(1)).text(); - Recipe.time.cook = $(metaText.get(2)).text(); - - Recipe.servings = metaText.last().text(); + let metaText = $(".meta-text").each((i, el) => { + let text = $(el).text(); + if (text.includes("Prep:")) { + Recipe.time.prep = text.replace("Prep: ", "").trim(); + } else if (text.includes("Cook: ")) { + Recipe.time.cook = text.replace("Cook:", "").trim(); + } else if (text.includes("Total: ")) { + Recipe.time.total = text.replace("Total:", "").trim(); + } else if (text.includes("Servings: ")) { + Recipe.servings = text.replace("Servings: ", "").trim(); + } + }); if ( !Recipe.name || diff --git a/test/constants/eatingwellConstants.js b/test/constants/eatingwellConstants.js index ae1df28..742a794 100644 --- a/test/constants/eatingwellConstants.js +++ b/test/constants/eatingwellConstants.js @@ -92,6 +92,6 @@ module.exports = { }, servings: "6", image: - "https://imagesvc.meredithcorp.io/v3/mm/image?q=85&c=sc&poi=face&w=640&h=335&url=https%3A%2F%2Fcf-images.us-east-1.prod.boltdns.net%2Fv1%2Fstatic%2F5118192885001%2Fc9b189d6-367e-4c94-8b05-f805363ae20f%2Fc185934c-9360-4f85-b766-0edbbfd1a583%2F640x360%2Fmatch%2Fimage.jpg" + "https://imagesvc.meredithcorp.io/v3/mm/image?q=85&c=sc&poi=face&w=960&h=503&url=https%3A%2F%2Fstatic.onecms.io%2Fwp-content%2Fuploads%2Fsites%2F44%2F2019%2F08%2F26231112%2F3750024.jpg" } }; diff --git a/test/constants/gimmedeliciousConstants.js b/test/constants/gimmedeliciousConstants.js new file mode 100644 index 0000000..f9209d3 --- /dev/null +++ b/test/constants/gimmedeliciousConstants.js @@ -0,0 +1,44 @@ +module.exports = { + testUrl: "https://gimmedelicious.com/creamy-spinach-and-mushroom-pasta-bake", + invalidUrl: "https://gimmedelicious.com/not_real", + invalidDomainUrl: "www.invalid.com", + nonRecipeUrl: "https://gimmedelicious.com/shop/", + expectedRecipe: { + name: "Creamy Spinach and Mushroom Pasta Bake", + ingredients: [ + "12 oz pasta uncooked", + "2 tablespoons unsalted butter", + "1 small onion diced", + "1 pound mushrooms of choice thinly sliced", + "2 cloves garlic minced", + "3 cups baby spinach", + "1 teaspoon italian seasoning", + "1/2 tsp salt", + "1/4 tsp pepper", + "1 tablespoon all-purpose flour", + "1/2 cup vegetable broth or water", + "1 cup light cream or half and half", + "1/4 cup freshly grated Parmesan", + "1 cup mozzarella cheese", + "2 tablespoons chopped fresh parsley leaves" + ], + instructions: [ + "Pre-heat oven to 375F.In a large pot of boiling salted water, cook pasta according to package instructions; drain well. Set aside.", + "Melt butter in a large skillet over medium heat. onion and mushrooms, cook for 2-3 minute or until the mushrooms are soft and tender. Add garlic, spinach, italian seasoning, and salt + pepper. cook for another minute.", + "Whisk in flour until lightly browned, about 1 minute. Gradually whisk in vegetable broth and then cream, and cook, whisking constantly, until incorporated, about 1-2 minutes. Stir in parmesan just before turning off heat.", + "Pour cooked pasta into a large 13×9 baking dish. Top with spinach mushroom cream sauce. Drizzle with mozzarella cheese. Bake for 18-20 minutes or until bubbly." + ], + tags: ["mushrooms", "parmesan", "pasta", "spinach"], + time: { + prep: "5 minutes", + cook: "25 minutes", + active: "", + inactive: "", + ready: "", + total: "30 minutes" + }, + servings: "6", + image: + "https://i2.wp.com/gimmedelicious.com/wp-content/uploads/2020/12/Image-11.jpg" + } +}; diff --git a/test/constants/julieblannerConstants.js b/test/constants/julieblannerConstants.js new file mode 100644 index 0000000..1c3ec57 --- /dev/null +++ b/test/constants/julieblannerConstants.js @@ -0,0 +1,42 @@ +module.exports = { + testUrl: "https://julieblanner.com/chicken-enchiladas/", + invalidUrl: "https://julieblanner.com/not_real", + invalidDomainUrl: "www.invalid.com", + nonRecipeUrl: "https://julieblanner.com/aboutjulie", + expectedRecipe: { + name: "Chicken Enchiladas", + ingredients: [ + "2 tablespoons oil canola, vegetable, olive or butter", + "1 cup white onion chopped (about 1 small onion)", + "2 boneless, skinless chicken breasts cubed", + "1 4 ounce can diced green chilies", + "½ teaspoon salt", + "½ teaspoon pepper", + "1¼ cup enchilada sauce (homemade or 10 ounce can)", + '8 8" flour tortillas', + "3 cups cheese shredded (Mexican blend, Monterey Jack, Pepper Jack, Cheddar or Cotija)", + "1 15 ounce can black beans drained" + ], + instructions: [ + "Preheat oven to 350°F.", + "In a skillet over medium heat, add oil and onion. Sauté about 3 minutes until the onion is tender and translucent.", + "Add chicken and green chilies. Brown about 6 minutes stirring occasionally.", + "Grease 9×13 baking dish. Spread 1/4 cup enchilada sauce in bottom of dish.", + "In the center of each tortilla, layer with 1/8th of chicken leaving room at both edges. Add a spoonful of black beans and approximately 1 ounce shredded cheese.", + "Fold tortilla over the filling and tightly wrap. Place in baking dish. Top generously with remaining enchilada sauce and cheese.", + "Bake 20-25 minutes until cheese is melted and tortillas slightly crisp and brown." + ], + tags: [], + time: { + prep: "20 mins", + cook: "20 mins", + active: "", + inactive: "", + ready: "", + total: "40 mins" + }, + servings: "4", + image: + "https://julieblanner.com/wp-content/uploads/2020/09/easy-chicken-enchilada-recipe-2.jpeg" + } +}; diff --git a/test/constants/melskitchencafeConstants.js b/test/constants/melskitchencafeConstants.js new file mode 100644 index 0000000..bb3b4a5 --- /dev/null +++ b/test/constants/melskitchencafeConstants.js @@ -0,0 +1,37 @@ +module.exports = { + testUrl: + "https://www.melskitchencafe.com/bbq-pulled-pork-sandwiches-slow-cooker/", + invalidUrl: "https://www.melskitchencafe.com/not_real", + invalidDomainUrl: "www.invalid.com", + nonRecipeUrl: "https://www.melskitchencafe.com/about/", + expectedRecipe: { + name: "BBQ Pulled Pork Sandwiches", + ingredients: [ + "3 to 4 pounds boneless pork shoulder, pork butt or pork sirloin roast", + "1 teaspoon salt (I use coarse, kosher salt)", + "1/2 teaspoon black pepper (I use coarsely ground)", + "2 cups water or low-sodium chicken broth", + "1 to 2 tablespoons liquid smoke", + "2 to 3 cups BBQ sauce (plus more for serving)" + ], + instructions: [ + "Cut the pork roast into large 4-inch pieces (optional, but helps cook a bit faster and more evenly). Season the pork on all sides with salt and pepper.", + "Slow Cooker Directions: add water or broth and liquid smoke to slow cooker. Add pork. Cover and cook on low 8-10 hours or high for 5-6 hours, until the pork is fall-apart tender.", + "Pressure Cooker Directions: Decrease the water/broth to 1 cup. Add the water or broth, pork and liquid smoke to an electric pressure cooker. Secure the lid, set the valve to seal, and cook on high pressure for 55-60 minutes. Let the pressure naturally release for 10 minutes (or all the way). Quick release any remaining pressure.", + "Remove the pork from the slow cooker or pressure cooker and discard most of the remaining liquid (I leave about 1/4 cup or so). Shred the pork using a couple of forks - it should easily fall apart into pieces. Place the meat back in the slow cooker or pressure cooker. Add the BBQ sauce and heat through (or keep on warm for several hours).", + "Serve on buns with extra barbecue sauce." + ], + tags: [], + time: { + prep: "15 minutes", + cook: "8 hours", + active: "", + inactive: "", + ready: "", + total: "8 hours 15 minutes" + }, + servings: "8-12 servings", + image: + "https://www.melskitchencafe.com/wp-content/uploads/2010/08/bbq-pork-sandwich1.jpg" + } +}; diff --git a/test/constants/tasteofhomeConstants.js b/test/constants/tasteofhomeConstants.js new file mode 100644 index 0000000..7a134ae --- /dev/null +++ b/test/constants/tasteofhomeConstants.js @@ -0,0 +1,64 @@ +module.exports = { + testUrl: "https://www.tasteofhome.com/recipes/artichoke-chicken", + invalidUrl: "https://www.tasteofhome.com/recipes/not_real", + invalidDomainUrl: "www.invalid.com", + nonRecipeUrl: "https://www.tasteofhome.com/recipes/", + expectedRecipe: { + name: "Artichoke Chicken", + ingredients: [ + "8 boneless skinless chicken breast halves (4 ounces each)", + "2 tablespoons butter", + "2 jars (6 ounces each) marinated quartered artichoke hearts, drained", + "1 jar (4-1/2 ounces) whole mushrooms, drained", + "1/2 cup chopped onion", + "1/3 cup all-purpose flour", + "1-1/2 teaspoons dried rosemary, crushed", + "3/4 teaspoon salt", + "1/4 teaspoon pepper", + "2 cups chicken broth or 1 cup broth and 1 cup dry white wine", + "Hot cooked noodles", + "Minced fresh parsley" + ], + instructions: [ + "In a large skillet, brown chicken in butter. Remove chicken to an ungreased 13x9-in. baking dish. Arrange artichokes and mushrooms on top of chicken; set aside.", + "Saute onion in pan juices until crisp-tender. Combine the flour, rosemary, salt and pepper. Stir into pan until blended. Add chicken broth. Bring to a boil; cook and stir until thickened and bubbly, about 2 minutes. Spoon over chicken.", + "Bake, uncovered, at 350° until a thermometer inserted in the chicken reads 165°, about 40 minutes. Serve with noodles and sprinkle with parsley. Freeze option: Cool unbaked casserole; cover and freeze. To use, partially thaw in refrigerator overnight. Remove from refrigerator 30 minutes before baking. Preheat oven to 350°. Bake casserole as directed, increasing time as necessary to heat through and for a thermometer inserted in the chicken to read 165°." + ], + tags: [ + "13x9", + "Artichoke Hearts", + "Artichokes", + "Bakeware", + "Baking Casseroles & Savories", + "Boneless Chicken Breasts", + "Chicken", + "Cooking Style", + "Diabetic", + "Dinner", + "Easy", + "Freezer-Friendly", + "Gear", + "Health & Wellness", + "Healthy Eating", + "Ingredients", + "Meal Types", + "Meat & Poultry", + "Recipes", + "Sauteing", + "Techniques", + "Vegetables", + "Winning Recipes" + ], + time: { + prep: "15 min.", + cook: "40 min.", + active: "", + inactive: "", + ready: "", + total: "" + }, + servings: "8 servings", + image: + "https://www.tasteofhome.com/wp-content/uploads/2018/01/Artichoke-Chicken_EXPS_13X9BZ19_24_B10_04_5b-6.jpg" + } +}; diff --git a/test/constants/theblackpeppercornConstants.js b/test/constants/theblackpeppercornConstants.js new file mode 100644 index 0000000..2a9f4fb --- /dev/null +++ b/test/constants/theblackpeppercornConstants.js @@ -0,0 +1,42 @@ +module.exports = { + testUrl: "https://www.theblackpeppercorn.com/how-to-cook-a-smoked-picnic-ham", + invalidUrl: "https://www.theblackpeppercorn.com//not_real", + invalidDomainUrl: "www.invalid.com", + nonRecipeUrl: "https://www.theblackpeppercorn.com/about-me/", + expectedRecipe: { + name: "How to Cook a Picnic Ham - Smoked Pork Shoulder", + ingredients: [ + "1 smoked picnic ham (5-8 pounds)", + "2 oranges, peeled", + "1 1/2 cups brown sugar", + "1/2 cup vinegar", + "1/3 cup honey", + "2 tbsp mustard", + "1 tsp cinnamon", + "1 tsp salt", + "1/4 tsp cayenne pepper" + ], + instructions: [ + "Preheat oven to 350F", + "Place picnic ham on a large roasting pan or baking dish, fat side up. Pour 3/4 cup of water into the bottom of the baking dish.", + "Cover roasting pan with foil and bake in the oven for 1 hour. This allows the rind to be removed easily.", + "Remove the foil and peel the rind off the top of the fat cap. Cut cross check slits into the fat and about 1/2 inch into the meat of the ham.", + "Puree remaining ingredients (oranges, brown sugar, vinegar, honey, mustard, cinnamon, salt and cayenne) in a blender to make the glaze. Brush some of the glaze all over the ham, making sure to get into the slits.", + "Bake for another 2 hours, uncovered. Brush the glaze after 1 hour cooking time and then again about 30 minutes later. Bake the remaining 30 minutes.", + "Once done cooking, the fat should be starting to crisp and the glaze nicely caramelized. Let the ham rest for about 5 minutes before carving.", + "Carve the ham into nice sized serving slices. Serve with glazed carrots, potatoes, squash and more!" + ], + tags: [], + time: { + prep: "10 minutes", + cook: "3 hours", + active: "", + inactive: "", + ready: "", + total: "3 hours 10 minutes" + }, + servings: "12", + image: + "https://www.theblackpeppercorn.com/wp-content/uploads/2017/06/How-to-Cook-a-Picnic-Shoulder-Ham-hires.jpg" + } +}; diff --git a/test/constants/therecipecriticConstants.js b/test/constants/therecipecriticConstants.js new file mode 100644 index 0000000..efe37d4 --- /dev/null +++ b/test/constants/therecipecriticConstants.js @@ -0,0 +1,35 @@ +module.exports = { + testUrl: "https://therecipecritic.com/creamy-parmesan-spaghetti/", + invalidUrl: "https://therecipecritic.com/not_real", + invalidDomainUrl: "www.invalid.com", + nonRecipeUrl: "https://therecipecritic.com/food-blogger/", + expectedRecipe: { + name: "Creamy Parmesan Spaghetti", + ingredients: [ + "12 ounces spaghetti noodles", + "1 tablespoon butter", + "3 teaspoons minced garlic", + "1 cup heavy cream", + "2/3 cup shaved parmesan cheese plus more for topping", + "salt and pepper to taste" + ], + instructions: [ + "Cook spaghetti noodles according to package's instructions. Drain and set aside.", + "Add butter to a large skillet and melt over medium heat. Add garlic and stir until fragrant (2-3 minutes). Transfer spaghetti to the pan and stir to coat in the garlic butter.", + "Add heavy cream and parmesan to pan and stir until parmesan is completely melted and combined and noodles are coated.", + "Season with salt and pepper to taste, sprinkle with parmesan cheese and serve immediately." + ], + tags: [], + time: { + prep: "5 minutes", + cook: "10 minutes", + active: "", + inactive: "", + ready: "", + total: "15 minutes" + }, + servings: "4", + image: + "https://therecipecritic.com/wp-content/uploads/2016/10/garlic-parmesan-spaghetti-1sm.jpg" + } +}; diff --git a/test/gimmedelicious.test.js b/test/gimmedelicious.test.js new file mode 100644 index 0000000..0433b9d --- /dev/null +++ b/test/gimmedelicious.test.js @@ -0,0 +1,11 @@ +"use strict"; +const commonRecipeTest = require("./helpers/commonRecipeTest"); +const gimmeDelicious = require("../scrapers/gimmedelicious"); +const Constants = require("./constants/gimmedeliciousConstants"); + +commonRecipeTest( + "gimmeDelicious", + gimmeDelicious, + Constants, + "gimmedelicious.com/" +); diff --git a/test/julieblanner.test.js b/test/julieblanner.test.js new file mode 100644 index 0000000..7a8c754 --- /dev/null +++ b/test/julieblanner.test.js @@ -0,0 +1,6 @@ +"use strict"; +const commonRecipeTest = require("./helpers/commonRecipeTest"); +const julieBlanner = require("../scrapers/julieblanner"); +const Constants = require("./constants/julieblannerConstants"); + +commonRecipeTest("julieBlanner", julieBlanner, Constants, "julieblanner.com/"); diff --git a/test/melskitchencafe.test.js b/test/melskitchencafe.test.js new file mode 100644 index 0000000..3844431 --- /dev/null +++ b/test/melskitchencafe.test.js @@ -0,0 +1,11 @@ +"use strict"; +const commonRecipeTest = require("./helpers/commonRecipeTest"); +const melsKitchenCafe = require("../scrapers/melskitchencafe"); +const Constants = require("./constants/melskitchencafeConstants"); + +commonRecipeTest( + "melsKitchenCafe", + melsKitchenCafe, + Constants, + "melskitchencafe.com/" +); diff --git a/test/tasteofhome.test.js b/test/tasteofhome.test.js new file mode 100644 index 0000000..c4ff813 --- /dev/null +++ b/test/tasteofhome.test.js @@ -0,0 +1,11 @@ +"use strict"; +const commonRecipeTest = require("./helpers/commonRecipeTest"); +const tasteOfHome = require("../scrapers/tasteofhome"); +const Constants = require("./constants/tasteofhomeConstants"); + +commonRecipeTest( + "tasteOfHome", + tasteOfHome, + Constants, + "tasteofhome.com/recipes/" +); diff --git a/test/theblackpeppercorn.test.js b/test/theblackpeppercorn.test.js new file mode 100644 index 0000000..e027452 --- /dev/null +++ b/test/theblackpeppercorn.test.js @@ -0,0 +1,11 @@ +"use strict"; +const commonRecipeTest = require("./helpers/commonRecipeTest"); +const theBlackPeppercorn = require("../scrapers/theblackpeppercorn"); +const Constants = require("./constants/theblackpeppercornConstants"); + +commonRecipeTest( + "theBlackPeppercorn", + theBlackPeppercorn, + Constants, + "theblackpeppercorn.com/" +); diff --git a/test/therecipecritic.test.js b/test/therecipecritic.test.js new file mode 100644 index 0000000..d622c58 --- /dev/null +++ b/test/therecipecritic.test.js @@ -0,0 +1,11 @@ +"use strict"; +const commonRecipeTest = require("./helpers/commonRecipeTest"); +const theRecipeCritic = require("../scrapers/therecipecritic"); +const Constants = require("./constants/therecipecriticConstants"); + +commonRecipeTest( + "theRecipeCritic", + theRecipeCritic, + Constants, + "therecipecritic.com/" +); From 1fb12f9293c2aa6295fd50d369a1ba594de14ffe Mon Sep 17 00:00:00 2001 From: jadkins89 Date: Wed, 6 Jan 2021 17:30:48 -0700 Subject: [PATCH 15/15] removing unused module --- scrapers/woolworths.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scrapers/woolworths.js b/scrapers/woolworths.js index 4dd66e8..f4b3741 100644 --- a/scrapers/woolworths.js +++ b/scrapers/woolworths.js @@ -1,6 +1,4 @@ const request = require("request"); -const cheerio = require("cheerio"); - const RecipeSchema = require("../helpers/recipe-schema"); const urlRe = /\/(\d\d\d\d)\//; @@ -28,8 +26,6 @@ const woolworths = url => { }, (error, response, html) => { if (!error && response.statusCode === 200 && html) { - const $ = cheerio.load(html); - Recipe.image = html.ImageFilename; Recipe.name = html.Title.trim(); Recipe.ingredients = html.Ingredients.map(i =>