just-one-cookbook.ts 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import { Recipe, Ingredient } from "../../model";
  2. import { RecipeDetails, ComposedIngredients } from '../../model';
  3. import { parseIngredients } from '../index';
  4. import { getText, getTextList, rmEquivalence } from './../service';
  5. import R from 'ramda';
  6. const SELECTORS = {
  7. TITLE: 'div.wprm-recipe-name',
  8. PREP_TIME: 'span.wprm-recipe-prep_time-minutes',
  9. COOK_TIME: 'span.wprm-recipe-cook_time-minutes',
  10. SERVINGS: 'span.wprm-recipe-servings',
  11. INGREDIENTS: 'div.wprm-recipe-ingredient-group',
  12. ING: {
  13. AMOUNT: 'span.wprm-recipe-ingredient-amount',
  14. UNIT: 'span.wprm-recipe-ingredient-unit',
  15. NAME: 'span.wprm-recipe-ingredient-name',
  16. NOTE: 'span.wprm-recipe-ingredient-notes'
  17. },
  18. SUB_RECIPE: 'div.wprm-recipe-ingredient-group-name',
  19. SUB_INGREDIENTS: 'li.wprm-recipe-ingredient',
  20. INSTRUCTIONS: 'div.wprm-recipe-instruction-text',
  21. TAGS: 'span.wprm-recipe-keyword',
  22. SUMMARY: 'div.wprm-recipe-summary',
  23. COURSE: 'span.wprm-recipe-course'
  24. }
  25. const getRecipeName = ($: CheerioSelector): string => {
  26. return $(SELECTORS.TITLE).text();
  27. }
  28. const getRecipeDetails = ($: CheerioSelector): RecipeDetails => {
  29. return {
  30. preparationTime: $(SELECTORS.PREP_TIME).text(),
  31. cookingTime: $(SELECTORS.COOK_TIME).text(),
  32. servings: Number($(SELECTORS.SERVINGS).text()),
  33. }
  34. };
  35. const getIngredients = ($: CheerioSelector): ComposedIngredients[] => {
  36. let ingredients: ComposedIngredients[] = [{name: '', ingredients: []}];
  37. const rawData = $(SELECTORS.INGREDIENTS);
  38. const cleanName = (element: CheerioElement, not: string): string => $(element).children().not(not).toArray().map(x => $(x).text()).join(' ');
  39. rawData.each((i, element) => {
  40. const last = ingredients.length - 1;
  41. const getIngredients = (li: Cheerio): Ingredient[] => li.toArray().map(el => ({
  42. ...parseIngredients(cleanName(el, SELECTORS.ING.NOTE)),
  43. note: $(el).find(SELECTORS.ING.NOTE).text(),
  44. _original: $(el).text().trim(),
  45. }));
  46. let subRecipe = $(element).find(SELECTORS.SUB_RECIPE);
  47. let subIngredients = $(element).find(SELECTORS.SUB_INGREDIENTS);
  48. if (subRecipe.contents().length) {
  49. ingredients.push({
  50. name: subRecipe.text(),
  51. ingredients: getIngredients(subIngredients),
  52. })
  53. } else {
  54. ingredients[last].ingredients = getIngredients(subIngredients);
  55. }
  56. })
  57. return ingredients;
  58. }
  59. const JOC_CONFIG = {
  60. name: 'Just One Cookbook',
  61. domain: 'justonecookbook',
  62. website: 'https://www.justonecookbook.com',
  63. scrapeRecipe: ($: CheerioSelector): Recipe => ({
  64. name: getText($)(SELECTORS.TITLE),
  65. author: { name: 'Nami' },
  66. details: getRecipeDetails($),
  67. ingredients: getIngredients($),
  68. instructions: getTextList($)(SELECTORS.INSTRUCTIONS),
  69. tags: (getText($)(SELECTORS.TAGS)).split(',').map(R.trim),
  70. course: [getText($)(SELECTORS.COURSE)],
  71. summary: getText($)(SELECTORS.SUMMARY),
  72. })
  73. }
  74. export default JOC_CONFIG;