Coverage for cookbook/helper/scrapers/cooksillustrated.py: 82%

38 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2023-12-29 01:02 +0100

1import json 

2from recipe_scrapers._abstract import AbstractScraper 

3 

4 

5class CooksIllustrated(AbstractScraper): 

6 @classmethod 

7 def host(cls, site='cooksillustrated'): 

8 return { 

9 'cooksillustrated': f"{site}.com", 

10 'americastestkitchen': f"{site}.com", 

11 'cookscountry': f"{site}.com", 

12 }.get(site) 

13 

14 def title(self): 

15 return self.schema.title() 

16 

17 def image(self): 

18 return self.schema.image() 

19 

20 def total_time(self): 

21 if not self.recipe: 

22 self.get_recipe() 

23 return self.recipe['recipeTimeNote'] 

24 

25 def yields(self): 

26 if not self.recipe: 

27 self.get_recipe() 

28 return self.recipe['yields'] 

29 

30 def ingredients(self): 

31 if not self.recipe: 

32 self.get_recipe() 

33 ingredients = [] 

34 for group in self.recipe['ingredientGroups']: 

35 ingredients += group['fields']['recipeIngredientItems'] 

36 return [ 

37 "{} {} {}{}".format( 

38 i['fields']['qty'] or '', 

39 i['fields']['measurement'] or '', 

40 i['fields']['ingredient']['fields']['title'] or '', 

41 i['fields']['postText'] or '' 

42 ) 

43 for i in ingredients 

44 ] 

45 

46 def instructions(self): 

47 if not self.recipe: 

48 self.get_recipe() 

49 if self.recipe.get('headnote', False): 

50 i = ['Note: ' + self.recipe.get('headnote', '')] 

51 else: 

52 i = [] 

53 return "\n".join( 

54 i 

55 + [self.recipe.get('whyThisWorks', '')] 

56 + [ 

57 instruction['fields']['content'] 

58 for instruction in self.recipe['instructions'] 

59 ] 

60 ) 

61 

62 def nutrients(self): 

63 raise NotImplementedError("This should be implemented.") 

64 

65 def get_recipe(self): 

66 j = json.loads(self.soup.find(type='application/json').string) 

67 name = list(j['props']['initialState']['content']['documents'])[0] 

68 self.recipe = j['props']['initialState']['content']['documents'][name]