prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Spider lowes is broken
  During the global build at 2021-06-02-14-42-40, spider **lowes** failed with **0 features** and **0 errors**.
  
  Here's [the log](https://data.alltheplaces.xyz/runs/2021-06-02-14-42-40/logs/lowes.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-06-02-14-42-40/output/lowes.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-06-02-14-42-40/output/lowes.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/lowes.py`
  Content:
  ```
  1 # -*- coding: utf-8 -*-
  2 import scrapy
  3 import re
  4 import json
  5 from locations.items import GeojsonPointItem
  6 from locations.hours import OpeningHours
  7 
  8 
  9 day_mapping = {'Monday': 'Mo', 'Tuesday': 'Tu', 'Wednesday': 'We', 'Thursday': 'Th', 'Friday': 'Fr', 'Saturday': 'Sa',
  10                'Sunday': 'Su'}
  11 
  12 
  13 class LowesSpider(scrapy.Spider):
  14     """"This spider scrapes Lowes retail store locations"""
  15     name = "lowes"
  16     item_attributes = { 'brand': "Lowe's", 'brand_wikidata': "Q1373493" }
  17     allowed_domains = ["lowes.com"]
  18     start_urls = ('https://www.lowes.com/Lowes-Stores',)
  19     download_delay = 0.5
  20 
  21     custom_settings = {
  22         'USER_AGENT': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36',
  23     }
  24 
  25     def parse_hours(self, store_hours):
  26         opening_hours = OpeningHours()
  27 
  28         for weekday in store_hours:
  29             day = weekday.get('day').get('day')
  30             open_time = weekday.get('day').get('open')
  31             hour, minute, sec = open_time.split('.')
  32             open_time_formatted = hour + ':' + minute
  33 
  34             close = weekday.get('day').get('close')
  35             hour, minute, sec = close.split('.')
  36             close_time_formatted = hour + ':' + minute
  37 
  38             if close_time_formatted in {'00:00', '24:00'}:
  39                 close_time_formatted = "23:59"
  40 
  41             opening_hours.add_range(day=day_mapping[day],
  42                                     open_time=open_time_formatted,
  43                                     close_time=close_time_formatted)
  44 
  45         return opening_hours.as_opening_hours()
  46 
  47     def parse_store(self, response):
  48         ref = re.search(r'.+/(.+)', response.url).group(1)
  49 
  50         script_content = response.xpath('//script[contains(text(),"storeHours")]/text()').extract_first()
  51         if not script_content:
  52             return
  53 
  54         # effectively strip off leading "window.__PRELOADED_STATE__ = " where
  55         # the rest is a json blob
  56         script_data = script_content.split(" = ", 1)[-1]
  57         json_data = json.loads(script_data)
  58         store_hours = json_data.get('storeHours')
  59 
  60         state_texts = response.xpath('//span[@itemprop="addressRegion"]/text()').extract()
  61         properties = {
  62             'lat': float(json_data['storeDetails']['lat']),
  63             'lon': float(json_data['storeDetails']['long']),
  64             'ref': ref,
  65             'addr_full': response.xpath('normalize-space(//span[@itemprop="streetAddress"]/text())').extract_first(),
  66             'city': response.xpath('normalize-space(//span[@itemprop="addressLocality"]/text())').extract_first(),
  67             'state': " ".join(text.strip() for text in state_texts if text.strip()),
  68             'postcode': response.xpath('normalize-space(//span[@itemprop="postalCode"]/text())').extract_first(),
  69             'phone': response.xpath('normalize-space(//meta[@itemprop="telephone"]/@content)').extract_first(),
  70             'website': response.request.url,
  71             'opening_hours': self.parse_hours(store_hours),
  72             'extras': {
  73                 'amenity:toilets': True,
  74             },
  75         }
  76 
  77         yield GeojsonPointItem(**properties)
  78 
  79     def parse_state(self, response):
  80         city_urls = response.xpath('//div[@class="v-spacing-small"]/a/@href').extract()
  81         for path in city_urls:
  82             yield scrapy.Request(response.urljoin(path), callback=self.parse_store)
  83 
  84     def parse(self, response):
  85         urls = response.xpath('//div[@id="mainContent"]//li[@role="listitem"]/a/@href').extract()
  86         for path in urls:
  87             yield scrapy.Request(response.urljoin(path), callback=self.parse_state)
  88
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/locations/spiders/lowes.py b/locations/spiders/lowes.py
  --- a/locations/spiders/lowes.py
  +++ b/locations/spiders/lowes.py
  @@ -6,16 +6,23 @@
   from locations.hours import OpeningHours
   
   
  -day_mapping = {'Monday': 'Mo', 'Tuesday': 'Tu', 'Wednesday': 'We', 'Thursday': 'Th', 'Friday': 'Fr', 'Saturday': 'Sa',
  -               'Sunday': 'Su'}
  +day_mapping = {
  +    'Monday': 'Mo',
  +    'Tuesday': 'Tu',
  +    'Wednesday': 'We',
  +    'Thursday': 'Th',
  +    'Friday': 'Fr',
  +    'Saturday': 'Sa',
  +    'Sunday': 'Su',
  +}
   
   
   class LowesSpider(scrapy.Spider):
       """"This spider scrapes Lowes retail store locations"""
       name = "lowes"
  -    item_attributes = { 'brand': "Lowe's", 'brand_wikidata': "Q1373493" }
  +    item_attributes = {'brand': "Lowe's", 'brand_wikidata': "Q1373493"}
       allowed_domains = ["lowes.com"]
  -    start_urls = ('https://www.lowes.com/Lowes-Stores',)
  +    start_urls = ('https://www.lowes.com/sitemap/store0.xml',)
       download_delay = 0.5
   
       custom_settings = {
  @@ -59,14 +66,14 @@
   
           state_texts = response.xpath('//span[@itemprop="addressRegion"]/text()').extract()
           properties = {
  -            'lat': float(json_data['storeDetails']['lat']),
  -            'lon': float(json_data['storeDetails']['long']),
  -            'ref': ref,
  -            'addr_full': response.xpath('normalize-space(//span[@itemprop="streetAddress"]/text())').extract_first(),
  -            'city': response.xpath('normalize-space(//span[@itemprop="addressLocality"]/text())').extract_first(),
  -            'state': " ".join(text.strip() for text in state_texts if text.strip()),
  -            'postcode': response.xpath('normalize-space(//span[@itemprop="postalCode"]/text())').extract_first(),
  -            'phone': response.xpath('normalize-space(//meta[@itemprop="telephone"]/@content)').extract_first(),
  +            'lat': json_data['storeDetails']['lat'],
  +            'lon': json_data['storeDetails']['long'],
  +            'ref': json_data['storeDetails']['id'],
  +            'addr_full': json_data['storeDetails']['address'],
  +            'city': json_data['storeDetails']['city'],
  +            'state': json_data['storeDetails']['state'],
  +            'postcode': json_data['storeDetails']['zip'],
  +            'phone': json_data['storeDetails']['phone'],
               'website': response.request.url,
               'opening_hours': self.parse_hours(store_hours),
               'extras': {
  @@ -76,12 +83,9 @@
   
           yield GeojsonPointItem(**properties)
   
  -    def parse_state(self, response):
  -        city_urls = response.xpath('//div[@class="v-spacing-small"]/a/@href').extract()
  -        for path in city_urls:
  -            yield scrapy.Request(response.urljoin(path), callback=self.parse_store)
  -
       def parse(self, response):
  -        urls = response.xpath('//div[@id="mainContent"]//li[@role="listitem"]/a/@href').extract()
  -        for path in urls:
  -            yield scrapy.Request(response.urljoin(path), callback=self.parse_state)
  +        response.selector.remove_namespaces()
  +        urls = response.xpath('//url/loc/text()').extract()
  +
  +        for url in urls:
  +            yield scrapy.Request(url, callback=self.parse_store)
  
verification_info: {"golden_diff": "diff --git a/locations/spiders/lowes.py b/locations/spiders/lowes.py\n--- a/locations/spiders/lowes.py\n+++ b/locations/spiders/lowes.py\n@@ -6,16 +6,23 @@\n from locations.hours import OpeningHours\n \n \n-day_mapping = {'Monday': 'Mo', 'Tuesday': 'Tu', 'Wednesday': 'We', 'Thursday': 'Th', 'Friday': 'Fr', 'Saturday': 'Sa',\n-               'Sunday': 'Su'}\n+day_mapping = {\n+    'Monday': 'Mo',\n+    'Tuesday': 'Tu',\n+    'Wednesday': 'We',\n+    'Thursday': 'Th',\n+    'Friday': 'Fr',\n+    'Saturday': 'Sa',\n+    'Sunday': 'Su',\n+}\n \n \n class LowesSpider(scrapy.Spider):\n     \"\"\"\"This spider scrapes Lowes retail store locations\"\"\"\n     name = \"lowes\"\n-    item_attributes = { 'brand': \"Lowe's\", 'brand_wikidata': \"Q1373493\" }\n+    item_attributes = {'brand': \"Lowe's\", 'brand_wikidata': \"Q1373493\"}\n     allowed_domains = [\"lowes.com\"]\n-    start_urls = ('https://www.lowes.com/Lowes-Stores',)\n+    start_urls = ('https://www.lowes.com/sitemap/store0.xml',)\n     download_delay = 0.5\n \n     custom_settings = {\n@@ -59,14 +66,14 @@\n \n         state_texts = response.xpath('//span[@itemprop=\"addressRegion\"]/text()').extract()\n         properties = {\n-            'lat': float(json_data['storeDetails']['lat']),\n-            'lon': float(json_data['storeDetails']['long']),\n-            'ref': ref,\n-            'addr_full': response.xpath('normalize-space(//span[@itemprop=\"streetAddress\"]/text())').extract_first(),\n-            'city': response.xpath('normalize-space(//span[@itemprop=\"addressLocality\"]/text())').extract_first(),\n-            'state': \" \".join(text.strip() for text in state_texts if text.strip()),\n-            'postcode': response.xpath('normalize-space(//span[@itemprop=\"postalCode\"]/text())').extract_first(),\n-            'phone': response.xpath('normalize-space(//meta[@itemprop=\"telephone\"]/@content)').extract_first(),\n+            'lat': json_data['storeDetails']['lat'],\n+            'lon': json_data['storeDetails']['long'],\n+            'ref': json_data['storeDetails']['id'],\n+            'addr_full': json_data['storeDetails']['address'],\n+            'city': json_data['storeDetails']['city'],\n+            'state': json_data['storeDetails']['state'],\n+            'postcode': json_data['storeDetails']['zip'],\n+            'phone': json_data['storeDetails']['phone'],\n             'website': response.request.url,\n             'opening_hours': self.parse_hours(store_hours),\n             'extras': {\n@@ -76,12 +83,9 @@\n \n         yield GeojsonPointItem(**properties)\n \n-    def parse_state(self, response):\n-        city_urls = response.xpath('//div[@class=\"v-spacing-small\"]/a/@href').extract()\n-        for path in city_urls:\n-            yield scrapy.Request(response.urljoin(path), callback=self.parse_store)\n-\n     def parse(self, response):\n-        urls = response.xpath('//div[@id=\"mainContent\"]//li[@role=\"listitem\"]/a/@href').extract()\n-        for path in urls:\n-            yield scrapy.Request(response.urljoin(path), callback=self.parse_state)\n+        response.selector.remove_namespaces()\n+        urls = response.xpath('//url/loc/text()').extract()\n+\n+        for url in urls:\n+            yield scrapy.Request(url, callback=self.parse_store)\n", "issue": "Spider lowes is broken\nDuring the global build at 2021-06-02-14-42-40, spider **lowes** failed with **0 features** and **0 errors**.\n\nHere's [the log](https://data.alltheplaces.xyz/runs/2021-06-02-14-42-40/logs/lowes.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-06-02-14-42-40/output/lowes.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-06-02-14-42-40/output/lowes.geojson))\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nimport scrapy\nimport re\nimport json\nfrom locations.items import GeojsonPointItem\nfrom locations.hours import OpeningHours\n\n\nday_mapping = {'Monday': 'Mo', 'Tuesday': 'Tu', 'Wednesday': 'We', 'Thursday': 'Th', 'Friday': 'Fr', 'Saturday': 'Sa',\n               'Sunday': 'Su'}\n\n\nclass LowesSpider(scrapy.Spider):\n    \"\"\"\"This spider scrapes Lowes retail store locations\"\"\"\n    name = \"lowes\"\n    item_attributes = { 'brand': \"Lowe's\", 'brand_wikidata': \"Q1373493\" }\n    allowed_domains = [\"lowes.com\"]\n    start_urls = ('https://www.lowes.com/Lowes-Stores',)\n    download_delay = 0.5\n\n    custom_settings = {\n        'USER_AGENT': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36',\n    }\n\n    def parse_hours(self, store_hours):\n        opening_hours = OpeningHours()\n\n        for weekday in store_hours:\n            day = weekday.get('day').get('day')\n            open_time = weekday.get('day').get('open')\n            hour, minute, sec = open_time.split('.')\n            open_time_formatted = hour + ':' + minute\n\n            close = weekday.get('day').get('close')\n            hour, minute, sec = close.split('.')\n            close_time_formatted = hour + ':' + minute\n\n            if close_time_formatted in {'00:00', '24:00'}:\n                close_time_formatted = \"23:59\"\n\n            opening_hours.add_range(day=day_mapping[day],\n                                    open_time=open_time_formatted,\n                                    close_time=close_time_formatted)\n\n        return opening_hours.as_opening_hours()\n\n    def parse_store(self, response):\n        ref = re.search(r'.+/(.+)', response.url).group(1)\n\n        script_content = response.xpath('//script[contains(text(),\"storeHours\")]/text()').extract_first()\n        if not script_content:\n            return\n\n        # effectively strip off leading \"window.__PRELOADED_STATE__ = \" where\n        # the rest is a json blob\n        script_data = script_content.split(\" = \", 1)[-1]\n        json_data = json.loads(script_data)\n        store_hours = json_data.get('storeHours')\n\n        state_texts = response.xpath('//span[@itemprop=\"addressRegion\"]/text()').extract()\n        properties = {\n            'lat': float(json_data['storeDetails']['lat']),\n            'lon': float(json_data['storeDetails']['long']),\n            'ref': ref,\n            'addr_full': response.xpath('normalize-space(//span[@itemprop=\"streetAddress\"]/text())').extract_first(),\n            'city': response.xpath('normalize-space(//span[@itemprop=\"addressLocality\"]/text())').extract_first(),\n            'state': \" \".join(text.strip() for text in state_texts if text.strip()),\n            'postcode': response.xpath('normalize-space(//span[@itemprop=\"postalCode\"]/text())').extract_first(),\n            'phone': response.xpath('normalize-space(//meta[@itemprop=\"telephone\"]/@content)').extract_first(),\n            'website': response.request.url,\n            'opening_hours': self.parse_hours(store_hours),\n            'extras': {\n                'amenity:toilets': True,\n            },\n        }\n\n        yield GeojsonPointItem(**properties)\n\n    def parse_state(self, response):\n        city_urls = response.xpath('//div[@class=\"v-spacing-small\"]/a/@href').extract()\n        for path in city_urls:\n            yield scrapy.Request(response.urljoin(path), callback=self.parse_store)\n\n    def parse(self, response):\n        urls = response.xpath('//div[@id=\"mainContent\"]//li[@role=\"listitem\"]/a/@href').extract()\n        for path in urls:\n            yield scrapy.Request(response.urljoin(path), callback=self.parse_state)\n", "path": "locations/spiders/lowes.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nimport scrapy\nimport re\nimport json\nfrom locations.items import GeojsonPointItem\nfrom locations.hours import OpeningHours\n\n\nday_mapping = {\n    'Monday': 'Mo',\n    'Tuesday': 'Tu',\n    'Wednesday': 'We',\n    'Thursday': 'Th',\n    'Friday': 'Fr',\n    'Saturday': 'Sa',\n    'Sunday': 'Su',\n}\n\n\nclass LowesSpider(scrapy.Spider):\n    \"\"\"\"This spider scrapes Lowes retail store locations\"\"\"\n    name = \"lowes\"\n    item_attributes = {'brand': \"Lowe's\", 'brand_wikidata': \"Q1373493\"}\n    allowed_domains = [\"lowes.com\"]\n    start_urls = ('https://www.lowes.com/sitemap/store0.xml',)\n    download_delay = 0.5\n\n    custom_settings = {\n        'USER_AGENT': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36',\n    }\n\n    def parse_hours(self, store_hours):\n        opening_hours = OpeningHours()\n\n        for weekday in store_hours:\n            day = weekday.get('day').get('day')\n            open_time = weekday.get('day').get('open')\n            hour, minute, sec = open_time.split('.')\n            open_time_formatted = hour + ':' + minute\n\n            close = weekday.get('day').get('close')\n            hour, minute, sec = close.split('.')\n            close_time_formatted = hour + ':' + minute\n\n            if close_time_formatted in {'00:00', '24:00'}:\n                close_time_formatted = \"23:59\"\n\n            opening_hours.add_range(day=day_mapping[day],\n                                    open_time=open_time_formatted,\n                                    close_time=close_time_formatted)\n\n        return opening_hours.as_opening_hours()\n\n    def parse_store(self, response):\n        ref = re.search(r'.+/(.+)', response.url).group(1)\n\n        script_content = response.xpath('//script[contains(text(),\"storeHours\")]/text()').extract_first()\n        if not script_content:\n            return\n\n        # effectively strip off leading \"window.__PRELOADED_STATE__ = \" where\n        # the rest is a json blob\n        script_data = script_content.split(\" = \", 1)[-1]\n        json_data = json.loads(script_data)\n        store_hours = json_data.get('storeHours')\n\n        state_texts = response.xpath('//span[@itemprop=\"addressRegion\"]/text()').extract()\n        properties = {\n            'lat': json_data['storeDetails']['lat'],\n            'lon': json_data['storeDetails']['long'],\n            'ref': json_data['storeDetails']['id'],\n            'addr_full': json_data['storeDetails']['address'],\n            'city': json_data['storeDetails']['city'],\n            'state': json_data['storeDetails']['state'],\n            'postcode': json_data['storeDetails']['zip'],\n            'phone': json_data['storeDetails']['phone'],\n            'website': response.request.url,\n            'opening_hours': self.parse_hours(store_hours),\n            'extras': {\n                'amenity:toilets': True,\n            },\n        }\n\n        yield GeojsonPointItem(**properties)\n\n    def parse(self, response):\n        response.selector.remove_namespaces()\n        urls = response.xpath('//url/loc/text()').extract()\n\n        for url in urls:\n            yield scrapy.Request(url, callback=self.parse_store)\n", "path": "locations/spiders/lowes.py"}]}