Repository: hhursev/recipe-scrapers

Issue:
bug: get_minutes returns precise-zero-minutes during fallback text matching case 
**Pre-filing checks**

- [x] I have searched for open issues that report the same problem
- [x] I have checked that the bug affects the latest version of the library

**The URL of the recipe(s) that are not being scraped correctly**

- https://panelinha.com.br/receita/arroz-sirio-com-frango

**The results you expect to see**

The `total_time` should _probably_ be returned as `None` -- the recipe describes it as "Pá-Pum" ('quickly'), however that's not the same as zero-time-at-all, and so it could be misleading to return zero.  I don't think we should attempt to estmate the duration, so `None` seems like the next-best alternative at the moment.

**The results (including any Python error messages) that you are seeing**

`total_time` returns zero for the text "Pá-Pum" in the recipe timing information (credit to @jknndy for discovering and [reporting that](https://github.com/hhursev/recipe-scrapers/pull/905/files#r1366177652) during #905).

Comments:

Patch:
diff --git a/recipe_scrapers/_utils.py b/recipe_scrapers/_utils.py
index fe3a401a..064046bd 100644
--- a/recipe_scrapers/_utils.py
+++ b/recipe_scrapers/_utils.py
@@ -75,6 +75,9 @@ def get_minutes(element, return_zero_on_not_found=False):  # noqa: C901: TODO
 
     matched = TIME_REGEX.search(time_text)
 
+    if matched is None or not any(matched.groupdict().values()):
+        return None
+
     minutes = int(matched.groupdict().get("minutes") or 0)
     hours_matched = matched.groupdict().get("hours")
     days_matched = matched.groupdict().get("days")
diff --git a/recipe_scrapers/nihhealthyeating.py b/recipe_scrapers/nihhealthyeating.py
index 2f89803c..435b3615 100644
--- a/recipe_scrapers/nihhealthyeating.py
+++ b/recipe_scrapers/nihhealthyeating.py
@@ -23,7 +23,9 @@ class NIHHealthyEating(AbstractScraper):
         if time_table is None:
             raise ElementNotFoundInHtml("Table with times was not found.")
 
-        return sum([get_minutes(td) for td in time_table.find_all("td")])
+        return sum(
+            [get_minutes(td) for td in time_table.find_all("td") if get_minutes(td)]
+        )
 
     def yields(self):
         # This content must be present for all recipes on this website.
diff --git a/recipe_scrapers/tastykitchen.py b/recipe_scrapers/tastykitchen.py
index 30774625..2531a3ca 100644
--- a/recipe_scrapers/tastykitchen.py
+++ b/recipe_scrapers/tastykitchen.py
@@ -12,12 +12,9 @@ class TastyKitchen(AbstractScraper):
         return self.soup.find("h1", {"itemprop": "name"}).get_text()
 
     def total_time(self):
-        return sum(
-            [
-                get_minutes(self.soup.find("time", {"itemprop": "prepTime"})),
-                get_minutes(self.soup.find("time", {"itemprop": "cookTime"})),
-            ]
-        )
+        prep_time = get_minutes(self.soup.find("time", {"itemprop": "prepTime"})) or 0
+        cook_time = get_minutes(self.soup.find("time", {"itemprop": "cookTime"})) or 0
+        return prep_time + cook_time
 
     def yields(self):
         return get_yields(self.soup.find("span", {"itemprop": "yield"}))


Test patch:
diff --git a/tests/library/test_utils.py b/tests/library/test_utils.py
index 1147865c..f561d0d2 100644
--- a/tests/library/test_utils.py
+++ b/tests/library/test_utils.py
@@ -72,6 +72,10 @@ class TestUtils(unittest.TestCase):
         text = "15 to 20 minutes"
         self.assertEqual(20, get_minutes(text))
 
+    def test_get_minutes_imprecise_description(self):
+        text = "Pá-Pum"
+        self.assertEqual(None, get_minutes(text))
+
     iso8601_fixtures = {
         "PT1H": 60,
         "PT20M": 20,
diff --git a/tests/test_kitchenstories.py b/tests/test_kitchenstories.py
index 56cf1eb4..73cfc9db 100644
--- a/tests/test_kitchenstories.py
+++ b/tests/test_kitchenstories.py
@@ -27,7 +27,7 @@ class TestKitchenStoriesScraper(ScraperTest):
         self.assertEqual(80, self.harvester_class.total_time())
 
     def test_cook_time(self):
-        self.assertEqual(0, self.harvester_class.cook_time())
+        self.assertEqual(None, self.harvester_class.cook_time())
 
     def test_prep_time(self):
         self.assertEqual(20, self.harvester_class.prep_time())
diff --git a/tests/test_panelinha_2.py b/tests/test_panelinha_2.py
index 21785723..4d15d811 100644
--- a/tests/test_panelinha_2.py
+++ b/tests/test_panelinha_2.py
@@ -16,7 +16,7 @@ class TestPanelinhaScraper(ScraperTest):
         self.assertEqual(self.harvester_class.author(), "Panelinha")
 
     def test_total_time(self):
-        self.assertEqual(0, self.harvester_class.total_time())
+        self.assertEqual(None, self.harvester_class.total_time())
 
     def test_yields(self):
         self.assertEqual("2 servings", self.harvester_class.yields())
diff --git a/tests/test_weightwatchers.py b/tests/test_weightwatchers.py
index 0b2bc234..dddc4ad6 100644
--- a/tests/test_weightwatchers.py
+++ b/tests/test_weightwatchers.py
@@ -27,7 +27,7 @@ class TestWeightwatchersScraper(ScraperTest):
         self.assertEqual(25, self.harvester_class.total_time())
 
     def test_cook_time(self):
-        self.assertEqual(0, self.harvester_class.cook_time())
+        self.assertEqual(None, self.harvester_class.cook_time())
 
     def test_prep_time(self):
         self.assertEqual(25, self.harvester_class.prep_time())