Repository: alltheplaces/alltheplaces

Issue:
Spider jimmy-johns is broken
During the global build at 2021-09-29-14-42-48, spider **jimmy-johns** failed with **0 features** and **1544 errors**.

Here's [the log](https://data.alltheplaces.xyz/runs/2021-09-29-14-42-48/logs/jimmy-johns.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-09-29-14-42-48/output/jimmy-johns.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-09-29-14-42-48/output/jimmy-johns.geojson))


Discussion:

Resolving patch:
diff --git a/locations/spiders/jimmy_johns.py b/locations/spiders/jimmy_johns.py
--- a/locations/spiders/jimmy_johns.py
+++ b/locations/spiders/jimmy_johns.py
@@ -1,61 +1,36 @@
 # -*- coding: utf-8 -*-
+from os import stat
 import scrapy
+from urllib import parse
 import json
-
 from locations.items import GeojsonPointItem
 
-STATES = ["AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DC", "DE", "FL", "GA",
-          "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD",
-          "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ",
-          "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC",
-          "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY"]
-HEADERS = { 'Content-Type': 'application/json' }
-JJBASE = 'https://www.jimmyjohns.com/webservices/Location/LocationServiceHandler.asmx/{}'
-CITIES = JJBASE.format('GetCitiesByStateNameAbbreviation')
-STORES = JJBASE.format('GetStoreAddressesByCityAndState')
+class TemplateSpider(scrapy.Spider):
+    name = "jimmy_johns"
+    allowed_domains = ["locations.jimmyjohns.com"]
+    start_urls = (
+        'https://locations.jimmyjohns.com/sitemap.xml',
+    )
 
-class JimmyJohnsSpider(scrapy.Spider):
-    name = "jimmy-johns"
-    item_attributes = { 'brand': "Jimmy John's", 'brand_wikidata': "Q1689380" }
-    allowed_domains = ["www.jimmyjohns.com"]
-    download_delay = 0.2
+    def parse(self, response):
+        stores = response.xpath('//url/loc[contains(text(),"sandwiches")]/text()').extract()
+        for store in stores:
+            yield scrapy.Request(response.urljoin(store), callback=self.parse_store)
 
-    def start_requests(self):
-        for state in STATES:
-            current_state = json.dumps({ 'state': state })
-            request = scrapy.Request(
-                CITIES,
-                method='POST',
-                body=current_state,
-                headers=HEADERS,
-                callback=self.parse_cities
-            )
-            request.meta['state'] = state
-            yield request
+    def parse_store(self, response):
+        data = json.loads(response.xpath('//script[@type="application/ld+json"]//text()').extract_first())
 
-    def parse_cities(self, response):
-        cities = json.loads(response.body)
-        for city in cities['d']:
-            current_city = json.dumps({ 'state': response.meta['state'], 'city': city })
-            request = scrapy.Request(
-                STORES,
-                method='POST',
-                body=current_city,
-                headers=HEADERS,
-                callback=self.parse
-            )
-            yield request
+        properties = {
+            'ref': data[0]['url'],
+            'addr_full': data[0]['address']['streetAddress'],
+            'city': data[0]['address']['addressLocality'],
+            'state': data[0]['address']['addressRegion'],
+            'postcode': data[0]['address']['postalCode'],
+            'website': response.url,
+            'lat': data[0]['geo']['latitude'],
+            'lon': data[0]['geo']['longitude'],
+        }
+        if data[0]['address']['telephone']:
+            properties['phone'] = data[0]['address']['telephone']
 
-    def parse(self, response):
-        stores = json.loads(response.body)
-        for store in stores['d']:
-            full = '{}, {}, {} {}'.format(store['address'], store['city'], store['state'], store['postalcode'])
-            yield GeojsonPointItem(
-                name=store['storename'],
-                addr_full=full,
-                opening_hours=store['hours'],
-                phone=store['telephone'],
-                ref=store['storeid'],
-                lon=float(store['lng']),
-                lat=float(store['lat']),
-            )
+        yield GeojsonPointItem(**properties)


Test patch: