We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Spider lenscrafters is broken
During the global build at 2021-08-25-14-42-15, spider **lenscrafters** failed with **0 features** and **1 errors**.

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

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `locations/spiders/lenscrafters.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 import json
3 import re
4 
5 import scrapy
6 
7 from locations.items import GeojsonPointItem
8 from locations.hours import OpeningHours
9 
10 
11 class LensCraftersSpider(scrapy.Spider):
12     name = "lenscrafters"
13     item_attributes = { 'brand': "Lenscrafters" }
14     allowed_domains = ['local.lenscrafters.com']
15     start_urls = [
16         'https://local.lenscrafters.com/'
17     ]
18 
19     def parse_hours(self, hours):
20         opening_hours = OpeningHours()
21         for group in hours:
22             if "Closed" in group:
23                 pass
24             else:
25                 days, open_time, close_time = re.search(r'([a-zA-Z,]+)\s([\d:]+)-([\d:]+)', group).groups()
26                 days = days.split(',')
27                 for day in days:
28                     opening_hours.add_range(day=day, open_time=open_time, close_time=close_time, time_format='%H:%M')
29 
30         return opening_hours.as_opening_hours()
31 
32     def parse(self, response):
33         urls = response.xpath(
34             '//a[@class="c-directory-list-content-item-link" or @class="c-location-grid-item-link"]/@href').extract()
35         # If cannot find 'c-directory-list-content-item-link' or 'c-location-grid-item-link' then this is a store page
36         if len(urls) == 0:
37             properties = {
38                 'name': response.xpath('//*[@class="location-name h1-normal"]/text()').extract_first(),
39                 'addr_full': response.xpath('//*[@class="c-address-street-1"]/text()').extract_first(),
40                 'city': response.xpath('//*[@class="c-address-city"]/text()').extract_first(),
41                 'state': response.xpath('//*[@class="c-address-state"]/text()').extract_first(),
42                 'postcode': response.xpath('//*[@class="c-address-postal-code"]/text()').extract_first(),
43                 'phone': response.xpath('//*[@id="phone-main"]/text()').extract_first(),
44                 'ref': "_".join(re.search(r".+/(.+?)/(.+?)/(.+?)/?(?:\.html|$)", response.url).groups()),
45                 'website': response.url,
46                 'lat': response.xpath('//*[@itemprop="latitude"]/@content').extract_first(),
47                 'lon': response.xpath('//*[@itemprop="longitude"]/@content').extract_first(),
48             }
49 
50             hours = self.parse_hours(response.xpath('//*[@itemprop="openingHours"]/@content').extract())
51             if hours:
52                 properties["opening_hours"] = hours
53 
54             yield GeojsonPointItem(**properties)
55         else:
56             for path in urls:
57                 yield scrapy.Request(url=response.urljoin(path), callback=self.parse)
58
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/locations/spiders/lenscrafters.py b/locations/spiders/lenscrafters.py
--- a/locations/spiders/lenscrafters.py
+++ b/locations/spiders/lenscrafters.py
@@ -10,7 +10,7 @@
 
 class LensCraftersSpider(scrapy.Spider):
     name = "lenscrafters"
-    item_attributes = { 'brand': "Lenscrafters" }
+    item_attributes = {'brand': "Lenscrafters"}
     allowed_domains = ['local.lenscrafters.com']
     start_urls = [
         'https://local.lenscrafters.com/'
@@ -30,21 +30,21 @@
         return opening_hours.as_opening_hours()
 
     def parse(self, response):
-        urls = response.xpath(
-            '//a[@class="c-directory-list-content-item-link" or @class="c-location-grid-item-link"]/@href').extract()
-        # If cannot find 'c-directory-list-content-item-link' or 'c-location-grid-item-link' then this is a store page
+        urls = response.xpath('//a[@class="Directory-listLink Link--directory"]/@href').extract()
+
+        # If cannot find 'Directory-listLink Link--directory' then this is a store page
         if len(urls) == 0:
             properties = {
-                'name': response.xpath('//*[@class="location-name h1-normal"]/text()').extract_first(),
-                'addr_full': response.xpath('//*[@class="c-address-street-1"]/text()').extract_first(),
-                'city': response.xpath('//*[@class="c-address-city"]/text()').extract_first(),
-                'state': response.xpath('//*[@class="c-address-state"]/text()').extract_first(),
-                'postcode': response.xpath('//*[@class="c-address-postal-code"]/text()').extract_first(),
-                'phone': response.xpath('//*[@id="phone-main"]/text()').extract_first(),
-                'ref': "_".join(re.search(r".+/(.+?)/(.+?)/(.+?)/?(?:\.html|$)", response.url).groups()),
-                'website': response.url,
-                'lat': response.xpath('//*[@itemprop="latitude"]/@content').extract_first(),
-                'lon': response.xpath('//*[@itemprop="longitude"]/@content').extract_first(),
+                'name': response.xpath('//h1[@id="location-name"]/text()').extract_first(),
+                'addr_full': response.xpath('//span[@class="c-address-street-1"]/text()').extract_first(),
+                'city': response.xpath('//span[@class="c-address-city"]/text()').extract_first(),
+                'state': response.xpath('//abbr[@class="c-address-state"]/text()').extract_first(),
+                'postcode': response.xpath('//span[@class="c-address-postal-code"]/text()').extract_first(),
+                'phone': response.xpath('//div[@id="phone-main"]/text()').extract_first(),
+                'ref': response.xpath('//link[@rel="canonical"]/@href').extract_first(),
+                'website': response.xpath('//link[@rel="canonical"]/@href').extract_first(),
+                'lat': response.xpath('//meta[@itemprop="latitude"]/@content').extract_first(),
+                'lon': response.xpath('//meta[@itemprop="longitude"]/@content').extract_first(),
             }
 
             hours = self.parse_hours(response.xpath('//*[@itemprop="openingHours"]/@content').extract())

{"golden_diff": "diff --git a/locations/spiders/lenscrafters.py b/locations/spiders/lenscrafters.py\n--- a/locations/spiders/lenscrafters.py\n+++ b/locations/spiders/lenscrafters.py\n@@ -10,7 +10,7 @@\n \n class LensCraftersSpider(scrapy.Spider):\n     name = \"lenscrafters\"\n-    item_attributes = { 'brand': \"Lenscrafters\" }\n+    item_attributes = {'brand': \"Lenscrafters\"}\n     allowed_domains = ['local.lenscrafters.com']\n     start_urls = [\n         'https://local.lenscrafters.com/'\n@@ -30,21 +30,21 @@\n         return opening_hours.as_opening_hours()\n \n     def parse(self, response):\n-        urls = response.xpath(\n-            '//a[@class=\"c-directory-list-content-item-link\" or @class=\"c-location-grid-item-link\"]/@href').extract()\n-        # If cannot find 'c-directory-list-content-item-link' or 'c-location-grid-item-link' then this is a store page\n+        urls = response.xpath('//a[@class=\"Directory-listLink Link--directory\"]/@href').extract()\n+\n+        # If cannot find 'Directory-listLink Link--directory' then this is a store page\n         if len(urls) == 0:\n             properties = {\n-                'name': response.xpath('//*[@class=\"location-name h1-normal\"]/text()').extract_first(),\n-                'addr_full': response.xpath('//*[@class=\"c-address-street-1\"]/text()').extract_first(),\n-                'city': response.xpath('//*[@class=\"c-address-city\"]/text()').extract_first(),\n-                'state': response.xpath('//*[@class=\"c-address-state\"]/text()').extract_first(),\n-                'postcode': response.xpath('//*[@class=\"c-address-postal-code\"]/text()').extract_first(),\n-                'phone': response.xpath('//*[@id=\"phone-main\"]/text()').extract_first(),\n-                'ref': \"_\".join(re.search(r\".+/(.+?)/(.+?)/(.+?)/?(?:\\.html|$)\", response.url).groups()),\n-                'website': response.url,\n-                'lat': response.xpath('//*[@itemprop=\"latitude\"]/@content').extract_first(),\n-                'lon': response.xpath('//*[@itemprop=\"longitude\"]/@content').extract_first(),\n+                'name': response.xpath('//h1[@id=\"location-name\"]/text()').extract_first(),\n+                'addr_full': response.xpath('//span[@class=\"c-address-street-1\"]/text()').extract_first(),\n+                'city': response.xpath('//span[@class=\"c-address-city\"]/text()').extract_first(),\n+                'state': response.xpath('//abbr[@class=\"c-address-state\"]/text()').extract_first(),\n+                'postcode': response.xpath('//span[@class=\"c-address-postal-code\"]/text()').extract_first(),\n+                'phone': response.xpath('//div[@id=\"phone-main\"]/text()').extract_first(),\n+                'ref': response.xpath('//link[@rel=\"canonical\"]/@href').extract_first(),\n+                'website': response.xpath('//link[@rel=\"canonical\"]/@href').extract_first(),\n+                'lat': response.xpath('//meta[@itemprop=\"latitude\"]/@content').extract_first(),\n+                'lon': response.xpath('//meta[@itemprop=\"longitude\"]/@content').extract_first(),\n             }\n \n             hours = self.parse_hours(response.xpath('//*[@itemprop=\"openingHours\"]/@content').extract())\n", "issue": "Spider lenscrafters is broken\nDuring the global build at 2021-08-25-14-42-15, spider **lenscrafters** failed with **0 features** and **1 errors**.\n\nHere's [the log](https://data.alltheplaces.xyz/runs/2021-08-25-14-42-15/logs/lenscrafters.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-08-25-14-42-15/output/lenscrafters.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-08-25-14-42-15/output/lenscrafters.geojson))\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nimport json\nimport re\n\nimport scrapy\n\nfrom locations.items import GeojsonPointItem\nfrom locations.hours import OpeningHours\n\n\nclass LensCraftersSpider(scrapy.Spider):\n    name = \"lenscrafters\"\n    item_attributes = { 'brand': \"Lenscrafters\" }\n    allowed_domains = ['local.lenscrafters.com']\n    start_urls = [\n        'https://local.lenscrafters.com/'\n    ]\n\n    def parse_hours(self, hours):\n        opening_hours = OpeningHours()\n        for group in hours:\n            if \"Closed\" in group:\n                pass\n            else:\n                days, open_time, close_time = re.search(r'([a-zA-Z,]+)\\s([\\d:]+)-([\\d:]+)', group).groups()\n                days = days.split(',')\n                for day in days:\n                    opening_hours.add_range(day=day, open_time=open_time, close_time=close_time, time_format='%H:%M')\n\n        return opening_hours.as_opening_hours()\n\n    def parse(self, response):\n        urls = response.xpath(\n            '//a[@class=\"c-directory-list-content-item-link\" or @class=\"c-location-grid-item-link\"]/@href').extract()\n        # If cannot find 'c-directory-list-content-item-link' or 'c-location-grid-item-link' then this is a store page\n        if len(urls) == 0:\n            properties = {\n                'name': response.xpath('//*[@class=\"location-name h1-normal\"]/text()').extract_first(),\n                'addr_full': response.xpath('//*[@class=\"c-address-street-1\"]/text()').extract_first(),\n                'city': response.xpath('//*[@class=\"c-address-city\"]/text()').extract_first(),\n                'state': response.xpath('//*[@class=\"c-address-state\"]/text()').extract_first(),\n                'postcode': response.xpath('//*[@class=\"c-address-postal-code\"]/text()').extract_first(),\n                'phone': response.xpath('//*[@id=\"phone-main\"]/text()').extract_first(),\n                'ref': \"_\".join(re.search(r\".+/(.+?)/(.+?)/(.+?)/?(?:\\.html|$)\", response.url).groups()),\n                'website': response.url,\n                'lat': response.xpath('//*[@itemprop=\"latitude\"]/@content').extract_first(),\n                'lon': response.xpath('//*[@itemprop=\"longitude\"]/@content').extract_first(),\n            }\n\n            hours = self.parse_hours(response.xpath('//*[@itemprop=\"openingHours\"]/@content').extract())\n            if hours:\n                properties[\"opening_hours\"] = hours\n\n            yield GeojsonPointItem(**properties)\n        else:\n            for path in urls:\n                yield scrapy.Request(url=response.urljoin(path), callback=self.parse)\n", "path": "locations/spiders/lenscrafters.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nimport json\nimport re\n\nimport scrapy\n\nfrom locations.items import GeojsonPointItem\nfrom locations.hours import OpeningHours\n\n\nclass LensCraftersSpider(scrapy.Spider):\n    name = \"lenscrafters\"\n    item_attributes = {'brand': \"Lenscrafters\"}\n    allowed_domains = ['local.lenscrafters.com']\n    start_urls = [\n        'https://local.lenscrafters.com/'\n    ]\n\n    def parse_hours(self, hours):\n        opening_hours = OpeningHours()\n        for group in hours:\n            if \"Closed\" in group:\n                pass\n            else:\n                days, open_time, close_time = re.search(r'([a-zA-Z,]+)\\s([\\d:]+)-([\\d:]+)', group).groups()\n                days = days.split(',')\n                for day in days:\n                    opening_hours.add_range(day=day, open_time=open_time, close_time=close_time, time_format='%H:%M')\n\n        return opening_hours.as_opening_hours()\n\n    def parse(self, response):\n        urls = response.xpath('//a[@class=\"Directory-listLink Link--directory\"]/@href').extract()\n\n        # If cannot find 'Directory-listLink Link--directory' then this is a store page\n        if len(urls) == 0:\n            properties = {\n                'name': response.xpath('//h1[@id=\"location-name\"]/text()').extract_first(),\n                'addr_full': response.xpath('//span[@class=\"c-address-street-1\"]/text()').extract_first(),\n                'city': response.xpath('//span[@class=\"c-address-city\"]/text()').extract_first(),\n                'state': response.xpath('//abbr[@class=\"c-address-state\"]/text()').extract_first(),\n                'postcode': response.xpath('//span[@class=\"c-address-postal-code\"]/text()').extract_first(),\n                'phone': response.xpath('//div[@id=\"phone-main\"]/text()').extract_first(),\n                'ref': response.xpath('//link[@rel=\"canonical\"]/@href').extract_first(),\n                'website': response.xpath('//link[@rel=\"canonical\"]/@href').extract_first(),\n                'lat': response.xpath('//meta[@itemprop=\"latitude\"]/@content').extract_first(),\n                'lon': response.xpath('//meta[@itemprop=\"longitude\"]/@content').extract_first(),\n            }\n\n            hours = self.parse_hours(response.xpath('//*[@itemprop=\"openingHours\"]/@content').extract())\n            if hours:\n                properties[\"opening_hours\"] = hours\n\n            yield GeojsonPointItem(**properties)\n        else:\n            for path in urls:\n                yield scrapy.Request(url=response.urljoin(path), callback=self.parse)\n", "path": "locations/spiders/lenscrafters.py"}]}