diff --git a/extruct/jsonld.py b/extruct/jsonld.py index 5cb713a6..706b061b 100644 --- a/extruct/jsonld.py +++ b/extruct/jsonld.py @@ -21,10 +21,11 @@ def extract(self, htmlstring, base_url=None, encoding="UTF-8"): return self.extract_items(tree, base_url=base_url) def extract_items(self, document, base_url=None): - return [item for items in map(self._extract_items, - self._xp_jsonld(document)) - for item in items - if item] + return [ + item + for items in map(self._extract_items, self._xp_jsonld(document)) + if items for item in items if item + ] def _extract_items(self, node): script = node.xpath('string()') @@ -33,7 +34,8 @@ def _extract_items(self, node): data = json.loads(script, strict=False) except ValueError: # sometimes JSON-decoding errors are due to leading HTML or JavaScript comments - data = json.loads(HTML_OR_JS_COMMENTLINE.sub('', script), strict=False) + data = json.loads( + HTML_OR_JS_COMMENTLINE.sub('', script), strict=False) if isinstance(data, list): return data elif isinstance(data, dict): diff --git a/tests/samples/songkick/jsonld_empty_item_test.html b/tests/samples/songkick/jsonld_empty_item_test.html new file mode 100644 index 00000000..923c2a34 --- /dev/null +++ b/tests/samples/songkick/jsonld_empty_item_test.html @@ -0,0 +1,1417 @@ + + + + + +53 Keto Diet Recipes | Taste of Home + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip links
+
+ + + +
Sign Up for Our Newsletters
+ + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/samples/songkick/jsonld_empty_item_test.jsonld b/tests/samples/songkick/jsonld_empty_item_test.jsonld new file mode 100644 index 00000000..52655319 --- /dev/null +++ b/tests/samples/songkick/jsonld_empty_item_test.jsonld @@ -0,0 +1,307 @@ +[ + { + "@context": "https://schema.org", + "@type": "ItemList", + "itemListElement": [ + { + "@type": "ListItem", + "position": 1, + "url": "https://www.tasteofhome.com/recipes/chicken-goat-cheese-skillet/" + }, + { + "@type": "ListItem", + "position": 2, + "url": "https://www.tasteofhome.com/recipes/cheesy-cauliflower-breadsticks/" + }, + { + "@type": "ListItem", + "position": 3, + "url": "https://www.tasteofhome.com/recipes/herbed-balsamic-chicken/" + }, + { + "@type": "ListItem", + "position": 4, + "url": "https://www.tasteofhome.com/recipes/garlic-dill-deviled-eggs/" + }, + { + "@type": "ListItem", + "position": 5, + "url": "https://www.tasteofhome.com/recipes/zucchini-crusted-pizza/" + }, + { + "@type": "ListItem", + "position": 6, + "url": "https://www.tasteofhome.com/recipes/creamy-dijon-chicken/" + }, + { + "@type": "ListItem", + "position": 7, + "url": "https://www.tasteofhome.com/recipes/naked-fish-tacos/" + }, + { + "@type": "ListItem", + "position": 8, + "url": "https://www.tasteofhome.com/recipes/denver-omelet-salad/" + }, + { + "@type": "ListItem", + "position": 9, + "url": "https://www.tasteofhome.com/recipes/balsamic-zucchini-saute/" + }, + { + "@type": "ListItem", + "position": 10, + "url": "https://www.tasteofhome.com/recipes/blackened-tilapia-with-zucchini-noodles/" + }, + { + "@type": "ListItem", + "position": 11, + "url": "https://www.tasteofhome.com/recipes/deviled-egg-spread/" + }, + { + "@type": "ListItem", + "position": 12, + "url": "https://www.tasteofhome.com/recipes/asparagus-mushroom-frittata/" + }, + { + "@type": "ListItem", + "position": 13, + "url": "https://www.tasteofhome.com/recipes/blue-cheese-pork-medallions/" + }, + { + "@type": "ListItem", + "position": 14, + "url": "https://www.tasteofhome.com/recipes/asparagus-cheese-frittata/" + }, + { + "@type": "ListItem", + "position": 15, + "url": "https://www.tasteofhome.com/recipes/oktoberfest-brats-with-mustard-sauce/" + }, + { + "@type": "ListItem", + "position": 16, + "url": "https://www.tasteofhome.com/recipes/shrimp-avocado-salad/" + }, + { + "@type": "ListItem", + "position": 17, + "url": "https://www.tasteofhome.com/recipes/sage-rubbed-salmon/" + }, + { + "@type": "ListItem", + "position": 18, + "url": "https://www.tasteofhome.com/recipes/cilantro-lime-shrimp/" + }, + { + "@type": "ListItem", + "position": 19, + "url": "https://www.tasteofhome.com/recipes/parmesan-roasted-broccoli/" + }, + { + "@type": "ListItem", + "position": 20, + "url": "https://www.tasteofhome.com/recipes/smoky-cauliflower-bites/" + }, + { + "@type": "ListItem", + "position": 21, + "url": "https://www.tasteofhome.com/recipes/avocado-crab-boats/" + }, + { + "@type": "ListItem", + "position": 22, + "url": "https://www.tasteofhome.com/recipes/parmesan-chicken/" + }, + { + "@type": "ListItem", + "position": 23, + "url": "https://www.tasteofhome.com/recipes/roasted-parmesan-carrots/" + }, + { + "@type": "ListItem", + "position": 24, + "url": "https://www.tasteofhome.com/recipes/coconut-curry-cauliflower-soup/" + }, + { + "@type": "ListItem", + "position": 25, + "url": "https://www.tasteofhome.com/recipes/brussels-sprouts-with-garlic-goat-cheese/" + }, + { + "@type": "ListItem", + "position": 26, + "url": "https://www.tasteofhome.com/recipes/juicy-delicious-mixed-spice-burgers/" + }, + { + "@type": "ListItem", + "position": 27, + "url": "https://www.tasteofhome.com/recipes/parmesan-asparagus/" + }, + { + "@type": "ListItem", + "position": 28, + "url": "https://www.tasteofhome.com/recipes/roasted-herb-lemon-cauliflower/" + }, + { + "@type": "ListItem", + "position": 29, + "url": "https://www.tasteofhome.com/recipes/shakshuka/" + }, + { + "@type": "ListItem", + "position": 30, + "url": "https://www.tasteofhome.com/recipes/mexican-cabbage-roll-soup/" + }, + { + "@type": "ListItem", + "position": 31, + "url": "https://www.tasteofhome.com/recipes/radish-carrot-cilantro-salad/" + }, + { + "@type": "ListItem", + "position": 32, + "url": "https://www.tasteofhome.com/recipes/vidalia-onion-swiss-dip/" + }, + { + "@type": "ListItem", + "position": 33, + "url": "https://www.tasteofhome.com/recipes/citrus-salmon-en-papillote/" + }, + { + "@type": "ListItem", + "position": 34, + "url": "https://www.tasteofhome.com/recipes/hot-chipotle-spinach-and-artichoke-dip-with-lime/" + }, + { + "@type": "ListItem", + "position": 35, + "url": "https://www.tasteofhome.com/recipes/grilled-ribeyes-with-greek-relish/" + }, + { + "@type": "ListItem", + "position": 36, + "url": "https://www.tasteofhome.com/recipes/asparagus-squash-red-pepper-saute/" + }, + { + "@type": "ListItem", + "position": 37, + "url": "https://www.tasteofhome.com/recipes/pressure-cooker-beef-brisket-in-beer/" + }, + { + "@type": "ListItem", + "position": 38, + "url": "https://www.tasteofhome.com/recipes/sausage-cobb-salad-lettuce-wraps/" + }, + { + "@type": "ListItem", + "position": 39, + "url": "https://www.tasteofhome.com/recipes/garlic-asiago-cauliflower-rice/" + }, + { + "@type": "ListItem", + "position": 40, + "url": "https://www.tasteofhome.com/recipes/cod-and-asparagus-bake/" + }, + { + "@type": "ListItem", + "position": 41, + "url": "https://www.tasteofhome.com/recipes/sauteed-squash-with-tomatoes-onions/" + }, + { + "@type": "ListItem", + "position": 42, + "url": "https://www.tasteofhome.com/recipes/roasted-cauliflower-with-tahini-yogurt-sauce/" + }, + { + "@type": "ListItem", + "position": 43, + "url": "https://www.tasteofhome.com/recipes/cajun-sirloin-with-mushroom-leek-sauce/" + }, + { + "@type": "ListItem", + "position": 44, + "url": "https://www.tasteofhome.com/recipes/chicken-and-broccoli-with-dill-sauce/" + }, + { + "@type": "ListItem", + "position": 45, + "url": "https://www.tasteofhome.com/recipes/pancetta-and-mushroom-stuffed-chicken-breast/" + }, + { + "@type": "ListItem", + "position": 46, + "url": "https://www.tasteofhome.com/recipes/leeks-au-gratin/" + }, + { + "@type": "ListItem", + "position": 47, + "url": "https://www.tasteofhome.com/recipes/moroccan-cauliflower-and-almond-soup/" + }, + { + "@type": "ListItem", + "position": 48, + "url": "https://www.tasteofhome.com/recipes/chicken-nicoise-salad/" + }, + { + "@type": "ListItem", + "position": 49, + "url": "https://www.tasteofhome.com/recipes/shrimp-scampi-spinach-salad/" + }, + { + "@type": "ListItem", + "position": 50, + "url": "https://www.tasteofhome.com/recipes/spicy-thai-coconut-chicken-soup/" + }, + { + "@type": "ListItem", + "position": 51, + "url": "https://www.tasteofhome.com/recipes/better-brussels-sprouts/" + }, + { + "@type": "ListItem", + "position": 52, + "url": "https://www.tasteofhome.com/recipes/shiitake-and-manchego-scramble/" + }, + { + "@type": "ListItem", + "position": 53, + "url": "https://www.tasteofhome.com/recipes/slow-cooker-marinated-mushrooms/" + } + ] + }, + { + "@context": "https://schema.org", + "@type": "BlogPosting", + "headline": "53 Keto Diet Recipes", + "mainEntityOfPage": { + "@type": "WebPage", + "@id": "https://www.tasteofhome.com/collection/keto-diet-recipes/view-all/" + }, + "description": "These keto recipes will satisfy your low carb diet needs (some are more strict than others!).", + "datePublished": "2018-09-11", + "dateModified": "2018-10-05", + "author": [ + { + "@type": "Person", + "name": "Rashanda Cobbins" + } + ], + "image": { + "@type": "ImageObject", + "url": "https://www.tasteofhome.com/wp-content/uploads/2017/09/Chicken-Goat-Cheese-Skillet_EXPS_SDAM17_136810_B12_08_4b.jpg", + "height": 1200, + "width": 1200 + }, + "publisher": { + "@type": "Organization", + "name": "Taste of Home", + "logo": { + "@type": "ImageObject", + "url": "https://cdn1.tmbi.com/TOH/Images/toh-logo-red.gif", + "width": 335, + "height": 60 + } + } + } +] \ No newline at end of file diff --git a/tests/test_jsonld.py b/tests/test_jsonld.py index 98f17c64..47309ee9 100644 --- a/tests/test_jsonld.py +++ b/tests/test_jsonld.py @@ -14,7 +14,15 @@ def test_schemaorg_CreativeWork(self): def test_songkick(self): self.assertJsonLdCorrect( folder='songkick', - page='Elysian Fields Brooklyn Tickets, The Owl Music Parlor, 31 Oct 2015') + page= + 'Elysian Fields Brooklyn Tickets, The Owl Music Parlor, 31 Oct 2015' + ) + + def test_jsonld_empty_item(self): + self.assertJsonLdCorrect( + folder='songkick', + page='jsonld_empty_item_test' + ) def test_jsonld_with_comments(self): for page in ['JoinAction.001', 'AllocateAction.001']: