Repository: alltheplaces/alltheplaces

Issue:
Spider texas_roadhouse is broken
During the global build at 2021-05-26-14-42-23, spider **texas_roadhouse** failed with **0 features** and **1 errors**.

Here's [the log](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/logs/texas_roadhouse.log) and [the output](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/texas_roadhouse.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/texas_roadhouse.geojson))


Discussion:

Resolving patch:
diff --git a/locations/spiders/texas_roadhouse.py b/locations/spiders/texas_roadhouse.py
--- a/locations/spiders/texas_roadhouse.py
+++ b/locations/spiders/texas_roadhouse.py
@@ -1,7 +1,5 @@
 import json
-
 import scrapy
-
 from locations.items import GeojsonPointItem
 from locations.hours import OpeningHours
 
@@ -11,7 +9,7 @@ class TexasRoadhouseSpider(scrapy.Spider):
     item_attributes = { 'brand': "Texas Roadhouse", 'brand_wikidata': "Q7707945" }
     allowed_domains = ["www.texasroadhouse.com"]
     start_urls = (
-        'https://www.texasroadhouse.com/locations',
+        'https://www.texasroadhouse.com/sitemap.xml',
     )
 
     def parse_hours(self, store_hours):
@@ -20,8 +18,8 @@ def parse_hours(self, store_hours):
         for weekday in store_hours:
             # convert day from full Monday to Mo, etc
             day = weekday.get('day')[:2]
-            open_time = weekday.get('hours').get('open')
-            close_time = weekday.get('hours').get('close')
+            open_time = weekday.get('hours').get('openTime')
+            close_time = weekday.get('hours').get('closeTime')
             opening_hours.add_range(day=day,
                                     open_time=open_time,
                                     close_time=close_time,
@@ -30,30 +28,31 @@ def parse_hours(self, store_hours):
         return opening_hours.as_opening_hours()
 
     def parse(self, response):
-        script_content = response.xpath('//script[contains(text(),"__locations__")]/text()').extract_first()
-        # effectively strip off leading "window.__locations__ = " where
-        # the rest is a json blob
-        script_data = script_content.split(" = ", 1)[-1]
-        script_data = script_data.rstrip(";")
-        stores = json.loads(script_data)
-
-        for store in stores:
-            properties = {
-                'lat': store['gps_lat'],
-                'lon': store['gps_lon'],
-                'ref': store['url'],
-                'name': store['name'],
-                'addr_full': store['address1'],
-                'city': store['city'],
-                'state': store['state'],
-                'postcode': store['zip'],
-                'country': store['country'],
-                'phone': store['phone'],
-                'website': response.urljoin(store['url']),
-                'opening_hours': self.parse_hours(store['schedule']),
-                'extras': {
-                    'amenity:toilets': True,
-                },
-            }
-
-            yield GeojsonPointItem(**properties)
+        response.selector.remove_namespaces()
+        city_urls = response.xpath('//url/loc/text()').extract()
+        for path in city_urls:
+            if path.startswith('https://www.texasroadhouse.com/locations/'):
+                yield scrapy.Request(
+                    path.strip(),
+                    callback=self.parse_store,
+                )
+
+    def parse_store(self, response):
+        data = json.loads(response.xpath('//script/text()').extract_first()[22:-1])
+
+        properties = {
+            'lat': data['latitude'],
+            'lon': data['longitude'],
+            'ref': data['url'],
+            'name': data['name'],
+            'addr_full': data['address1'],
+            'city': data['city'],
+            'state': data['state'],
+            'postcode': data['postalCode'],
+            'country': data['countryCode'],
+            'phone': data['telephone'],
+            'website': response.urljoin(data['url']),
+            'opening_hours': self.parse_hours(data['schedule']),
+        }
+
+        yield GeojsonPointItem(**properties)


Test patch: