Repository: alltheplaces/alltheplaces

Issue:
Spider anthonys_restaurants is broken
During the global build at 2021-06-16-14-42-20, spider **anthonys_restaurants** failed with **0 features** and **0 errors**.

Here's [the log](https://data.alltheplaces.xyz/runs/2021-06-16-14-42-20/logs/anthonys_restaurants.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-06-16-14-42-20/output/anthonys_restaurants.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-06-16-14-42-20/output/anthonys_restaurants.geojson))


Discussion:

Resolving patch:
diff --git a/locations/spiders/anthonys_restaurants.py b/locations/spiders/anthonys_restaurants.py
--- a/locations/spiders/anthonys_restaurants.py
+++ b/locations/spiders/anthonys_restaurants.py
@@ -1,41 +1,49 @@
 # -*- coding: utf-8 -*-
+import json
+import re
+
 import scrapy
+
 from locations.items import GeojsonPointItem
 
 
 class AnthonysRestaurantsSpiders(scrapy.Spider):
     name = "anthonys_restaurants"
-    item_attributes = { 'brand': "Anthony's" }
+    item_attributes = {"brand": "Anthony's"}
     allowed_domains = ["www.anthonys.com"]
-    start_urls = (
-        'https://www.anthonys.com/restaurants/search/47.6062095/-122.3320708/2000',
-    )
+    start_urls = ("https://www.anthonys.com/restaurants/",)
 
     def parse(self, response):
-        for match in response.xpath("//markers/marker"):
-            fullAddress=match.xpath('.//@address').extract_first().replace('<br />', ',')
-
-            # Accounts for cases with second address line
-            if(len(fullAddress.split(",")) == 4):
-                cityString = fullAddress.split(",")[2].strip()
-                stateString = fullAddress.split(",")[3].strip().split(" ")[0].strip()
-                postString = fullAddress.split(",")[3].strip().split(" ")[1].strip()
-                addrLineOne = fullAddress.split(",")[0].strip()
-                addrLineTwo = fullAddress.split(",")[1].strip()
-                addrString = addrLineOne + ", " + addrLineTwo
-            else:
-                cityString = fullAddress.split(",")[1].strip()
-                stateString = fullAddress.split(",")[2].strip().split(" ")[0].strip()
-                postString = fullAddress.split(",")[2].strip().split(" ")[1].strip()
-                addrString = fullAddress.split(",")[0]
-
-            yield GeojsonPointItem(
-                ref=match.xpath('.//@title').extract_first().strip(),
-                lat=match.xpath('.//@lat').extract_first().strip(),
-                lon=match.xpath('.//@lng').extract_first().strip(),
-                addr_full=addrString,
-                city=cityString,
-                state=stateString,
-                postcode=postString,
-                phone=match.xpath('.//@phone').extract_first().replace(" ", ""),
-            )
+        script = response.css("#acf-block-locations-map-script-js-extra::text").get()
+        j = json.loads(script[script.find("{") : 1 + script.rfind("}")])
+        for row in j["restaurants"]:
+            meta = {"json": row}
+            yield scrapy.Request(row["link"], meta=meta, callback=self.parse_location)
+
+    def parse_location(self, response):
+        json_data = response.meta["json"]
+        address = json_data["address"]
+        # decode entities
+        name = scrapy.Selector(text=json_data["name"]).xpath("//text()").get()
+
+        # These are weird enough that there's no hope of parsing them, but
+        # clean the text up
+        hours = response.xpath('//strong[text()="Hours:"]/../text()').extract()
+        hours = ';'.join(s.strip().replace('\xa0', ' ') for s in hours)
+
+        properties = {
+            "ref": re.search(r"postid-(\d+)", response.css("body").attrib["class"])[1],
+            "lat": address["latitude"],
+            "lon": address["longitude"],
+            "addr_full": address["address"],
+            "city": address["city"],
+            "state": address["state"],
+            "postcode": address["zip_code"],
+            "name": name,
+            "website": response.url,
+            "phone": (
+                response.xpath("//*[starts-with(@href, 'tel:')]/@href").get() or ""
+            )[4:],
+            "opening_hours": hours,
+        }
+        return GeojsonPointItem(**properties)


Test patch: