prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Spider cvs is broken
  During the global build at 2021-08-18-14-42-26, spider **cvs** failed with **0 features** and **9870 errors**.
  
  Here's [the log](https://data.alltheplaces.xyz/runs/2021-08-18-14-42-26/logs/cvs.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-08-18-14-42-26/output/cvs.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-08-18-14-42-26/output/cvs.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/cvs.py`
  Content:
  ```
  1 import json
  2 import scrapy
  3 import re
  4 from locations.items import GeojsonPointItem
  5 from locations.hours import OpeningHours
  6 
  7 DAYS = [
  8     'Mo',
  9     'Tu',
  10     'We',
  11     'Th',
  12     'Fr',
  13     'Sa',
  14     'Su'
  15 ]
  16 
  17 
  18 class CVSSpider(scrapy.Spider):
  19 
  20     name = "cvs"
  21     item_attributes = { 'brand': "CVS", 'brand_wikidata': "Q2078880" }
  22     allowed_domains = ["www.cvs.com"]
  23     download_delay = 0.5
  24     start_urls = (
  25         'https://www.cvs.com/store-locator/cvs-pharmacy-locations',
  26     )
  27 
  28     def parse_hours(self, hours):
  29         opening_hours = OpeningHours()
  30 
  31         for group in hours:
  32             if 'closed' in group:
  33                 continue
  34             if 'open 24 hours' in group:
  35                 days = re.search(r'([a-zA-Z\-]+)\s+open 24 hours', group).groups()[0]
  36                 open_time, close_time = '00:00:00', '23:59:00'
  37             else:
  38                 try:
  39                     days, open_time, close_time = re.search(r'([a-zA-Z\-]+)\s+([\d:\sapm]+)-([\d:\sapm]+)', group).groups()
  40                 except AttributeError:
  41                     continue  # no hours listed, just day
  42             try:
  43                 start_day, end_day = days.split('-')
  44             except ValueError:
  45                 start_day, end_day = days, days
  46             for day in DAYS[DAYS.index(start_day):DAYS.index(end_day) + 1]:
  47                 if 'm' in open_time:
  48                     open_time = open_time.strip(' apm') + ":00"
  49                 if 'm' in close_time:
  50                     close_time = close_time.strip(' apm') + ":00"
  51                 opening_hours.add_range(day=day,
  52                                         open_time=open_time.strip(),
  53                                         close_time=close_time.strip(),
  54                                         time_format='%H:%M:%S')
  55 
  56         return opening_hours.as_opening_hours()
  57 
  58     def parse_stores(self, response):
  59         try:
  60             data = json.loads(response.xpath('//script[@type="application/ld+json" and contains(text(), "streetAddress")]/text()').extract_first())[0]
  61         except json.decoder.JSONDecodeError:
  62             # one malformed json body on this store:
  63             # https://www.cvs.com/store-locator/cvs-pharmacy-address/84+South+Avenue+tops+Plaza+-Hilton-NY-14468/storeid=5076
  64             data = response.xpath('//script[@type="application/ld+json" and contains(text(), "streetAddress")]/text()').extract_first()
  65             data = re.sub(r'"tops Plaza\s*"', '', data)
  66             data = json.loads(data)[0]
  67         except TypeError:
  68             return  # empty store page
  69 
  70         properties = {
  71             'name': data["name"],
  72             'ref': re.search(r'.+/?storeid=(.+)', response.url).group(1),
  73             'addr_full': data["address"]["streetAddress"].strip(', '),
  74             'city': data["address"]["addressLocality"],
  75             'state': data["address"]["addressRegion"],
  76             'postcode': data["address"]["postalCode"],
  77             'country': data["address"]["addressCountry"],
  78             'phone': data["address"].get("telephone"),
  79             'website': data.get("url") or response.url,
  80             'lat': float(data["geo"]["latitude"]),
  81             'lon': float(data["geo"]["longitude"]),
  82         }
  83 
  84         hours = self.parse_hours(data["openingHours"])
  85         if hours:
  86             properties["opening_hours"] = hours
  87 
  88         yield GeojsonPointItem(**properties)
  89 
  90     def parse_city_stores(self, response):
  91         stores = response.xpath('//div[@class="each-store"]')
  92 
  93         for store in stores:
  94 
  95             direction = store.xpath('normalize-space(.//span[@class="store-number"]/a/@href)').extract_first()
  96             if direction:
  97                 yield scrapy.Request(response.urljoin(direction), callback=self.parse_stores)
  98 
  99     def parse_state(self, response):
  100         city_urls = response.xpath('//div[@class="states"]/ul/li/a/@href').extract()
  101         for path in city_urls:
  102             yield scrapy.Request(response.urljoin(path), callback=self.parse_city_stores)
  103 
  104     def parse(self, response):
  105         urls = response.xpath('//div[@class="states"]/ul/li/a/@href').extract()
  106         for path in urls:
  107             yield scrapy.Request(response.urljoin(path), callback=self.parse_state)
  108
  ```
  --- 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/cvs.py b/locations/spiders/cvs.py
  --- a/locations/spiders/cvs.py
  +++ b/locations/spiders/cvs.py
  @@ -77,8 +77,8 @@
               'country': data["address"]["addressCountry"],
               'phone': data["address"].get("telephone"),
               'website': data.get("url") or response.url,
  -            'lat': float(data["geo"]["latitude"]),
  -            'lon': float(data["geo"]["longitude"]),
  +            'lat': data["geo"]["latitude"] or None,
  +            'lon': data["geo"]["longitude"] or None,
           }
   
           hours = self.parse_hours(data["openingHours"])
  
verification_info: {"golden_diff": "diff --git a/locations/spiders/cvs.py b/locations/spiders/cvs.py\n--- a/locations/spiders/cvs.py\n+++ b/locations/spiders/cvs.py\n@@ -77,8 +77,8 @@\n             'country': data[\"address\"][\"addressCountry\"],\n             'phone': data[\"address\"].get(\"telephone\"),\n             'website': data.get(\"url\") or response.url,\n-            'lat': float(data[\"geo\"][\"latitude\"]),\n-            'lon': float(data[\"geo\"][\"longitude\"]),\n+            'lat': data[\"geo\"][\"latitude\"] or None,\n+            'lon': data[\"geo\"][\"longitude\"] or None,\n         }\n \n         hours = self.parse_hours(data[\"openingHours\"])\n", "issue": "Spider cvs is broken\nDuring the global build at 2021-08-18-14-42-26, spider **cvs** failed with **0 features** and **9870 errors**.\n\nHere's [the log](https://data.alltheplaces.xyz/runs/2021-08-18-14-42-26/logs/cvs.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-08-18-14-42-26/output/cvs.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-08-18-14-42-26/output/cvs.geojson))\n", "before_files": [{"content": "import json\nimport scrapy\nimport re\nfrom locations.items import GeojsonPointItem\nfrom locations.hours import OpeningHours\n\nDAYS = [\n    'Mo',\n    'Tu',\n    'We',\n    'Th',\n    'Fr',\n    'Sa',\n    'Su'\n]\n\n\nclass CVSSpider(scrapy.Spider):\n\n    name = \"cvs\"\n    item_attributes = { 'brand': \"CVS\", 'brand_wikidata': \"Q2078880\" }\n    allowed_domains = [\"www.cvs.com\"]\n    download_delay = 0.5\n    start_urls = (\n        'https://www.cvs.com/store-locator/cvs-pharmacy-locations',\n    )\n\n    def parse_hours(self, hours):\n        opening_hours = OpeningHours()\n\n        for group in hours:\n            if 'closed' in group:\n                continue\n            if 'open 24 hours' in group:\n                days = re.search(r'([a-zA-Z\\-]+)\\s+open 24 hours', group).groups()[0]\n                open_time, close_time = '00:00:00', '23:59:00'\n            else:\n                try:\n                    days, open_time, close_time = re.search(r'([a-zA-Z\\-]+)\\s+([\\d:\\sapm]+)-([\\d:\\sapm]+)', group).groups()\n                except AttributeError:\n                    continue  # no hours listed, just day\n            try:\n                start_day, end_day = days.split('-')\n            except ValueError:\n                start_day, end_day = days, days\n            for day in DAYS[DAYS.index(start_day):DAYS.index(end_day) + 1]:\n                if 'm' in open_time:\n                    open_time = open_time.strip(' apm') + \":00\"\n                if 'm' in close_time:\n                    close_time = close_time.strip(' apm') + \":00\"\n                opening_hours.add_range(day=day,\n                                        open_time=open_time.strip(),\n                                        close_time=close_time.strip(),\n                                        time_format='%H:%M:%S')\n\n        return opening_hours.as_opening_hours()\n\n    def parse_stores(self, response):\n        try:\n            data = json.loads(response.xpath('//script[@type=\"application/ld+json\" and contains(text(), \"streetAddress\")]/text()').extract_first())[0]\n        except json.decoder.JSONDecodeError:\n            # one malformed json body on this store:\n            # https://www.cvs.com/store-locator/cvs-pharmacy-address/84+South+Avenue+tops+Plaza+-Hilton-NY-14468/storeid=5076\n            data = response.xpath('//script[@type=\"application/ld+json\" and contains(text(), \"streetAddress\")]/text()').extract_first()\n            data = re.sub(r'\"tops Plaza\\s*\"', '', data)\n            data = json.loads(data)[0]\n        except TypeError:\n            return  # empty store page\n\n        properties = {\n            'name': data[\"name\"],\n            'ref': re.search(r'.+/?storeid=(.+)', response.url).group(1),\n            'addr_full': data[\"address\"][\"streetAddress\"].strip(', '),\n            'city': data[\"address\"][\"addressLocality\"],\n            'state': data[\"address\"][\"addressRegion\"],\n            'postcode': data[\"address\"][\"postalCode\"],\n            'country': data[\"address\"][\"addressCountry\"],\n            'phone': data[\"address\"].get(\"telephone\"),\n            'website': data.get(\"url\") or response.url,\n            'lat': float(data[\"geo\"][\"latitude\"]),\n            'lon': float(data[\"geo\"][\"longitude\"]),\n        }\n\n        hours = self.parse_hours(data[\"openingHours\"])\n        if hours:\n            properties[\"opening_hours\"] = hours\n\n        yield GeojsonPointItem(**properties)\n\n    def parse_city_stores(self, response):\n        stores = response.xpath('//div[@class=\"each-store\"]')\n\n        for store in stores:\n\n            direction = store.xpath('normalize-space(.//span[@class=\"store-number\"]/a/@href)').extract_first()\n            if direction:\n                yield scrapy.Request(response.urljoin(direction), callback=self.parse_stores)\n\n    def parse_state(self, response):\n        city_urls = response.xpath('//div[@class=\"states\"]/ul/li/a/@href').extract()\n        for path in city_urls:\n            yield scrapy.Request(response.urljoin(path), callback=self.parse_city_stores)\n\n    def parse(self, response):\n        urls = response.xpath('//div[@class=\"states\"]/ul/li/a/@href').extract()\n        for path in urls:\n            yield scrapy.Request(response.urljoin(path), callback=self.parse_state)\n", "path": "locations/spiders/cvs.py"}], "after_files": [{"content": "import json\nimport scrapy\nimport re\nfrom locations.items import GeojsonPointItem\nfrom locations.hours import OpeningHours\n\nDAYS = [\n    'Mo',\n    'Tu',\n    'We',\n    'Th',\n    'Fr',\n    'Sa',\n    'Su'\n]\n\n\nclass CVSSpider(scrapy.Spider):\n\n    name = \"cvs\"\n    item_attributes = { 'brand': \"CVS\", 'brand_wikidata': \"Q2078880\" }\n    allowed_domains = [\"www.cvs.com\"]\n    download_delay = 0.5\n    start_urls = (\n        'https://www.cvs.com/store-locator/cvs-pharmacy-locations',\n    )\n\n    def parse_hours(self, hours):\n        opening_hours = OpeningHours()\n\n        for group in hours:\n            if 'closed' in group:\n                continue\n            if 'open 24 hours' in group:\n                days = re.search(r'([a-zA-Z\\-]+)\\s+open 24 hours', group).groups()[0]\n                open_time, close_time = '00:00:00', '23:59:00'\n            else:\n                try:\n                    days, open_time, close_time = re.search(r'([a-zA-Z\\-]+)\\s+([\\d:\\sapm]+)-([\\d:\\sapm]+)', group).groups()\n                except AttributeError:\n                    continue  # no hours listed, just day\n            try:\n                start_day, end_day = days.split('-')\n            except ValueError:\n                start_day, end_day = days, days\n            for day in DAYS[DAYS.index(start_day):DAYS.index(end_day) + 1]:\n                if 'm' in open_time:\n                    open_time = open_time.strip(' apm') + \":00\"\n                if 'm' in close_time:\n                    close_time = close_time.strip(' apm') + \":00\"\n                opening_hours.add_range(day=day,\n                                        open_time=open_time.strip(),\n                                        close_time=close_time.strip(),\n                                        time_format='%H:%M:%S')\n\n        return opening_hours.as_opening_hours()\n\n    def parse_stores(self, response):\n        try:\n            data = json.loads(response.xpath('//script[@type=\"application/ld+json\" and contains(text(), \"streetAddress\")]/text()').extract_first())[0]\n        except json.decoder.JSONDecodeError:\n            # one malformed json body on this store:\n            # https://www.cvs.com/store-locator/cvs-pharmacy-address/84+South+Avenue+tops+Plaza+-Hilton-NY-14468/storeid=5076\n            data = response.xpath('//script[@type=\"application/ld+json\" and contains(text(), \"streetAddress\")]/text()').extract_first()\n            data = re.sub(r'\"tops Plaza\\s*\"', '', data)\n            data = json.loads(data)[0]\n        except TypeError:\n            return  # empty store page\n\n        properties = {\n            'name': data[\"name\"],\n            'ref': re.search(r'.+/?storeid=(.+)', response.url).group(1),\n            'addr_full': data[\"address\"][\"streetAddress\"].strip(', '),\n            'city': data[\"address\"][\"addressLocality\"],\n            'state': data[\"address\"][\"addressRegion\"],\n            'postcode': data[\"address\"][\"postalCode\"],\n            'country': data[\"address\"][\"addressCountry\"],\n            'phone': data[\"address\"].get(\"telephone\"),\n            'website': data.get(\"url\") or response.url,\n            'lat': data[\"geo\"][\"latitude\"] or None,\n            'lon': data[\"geo\"][\"longitude\"] or None,\n        }\n\n        hours = self.parse_hours(data[\"openingHours\"])\n        if hours:\n            properties[\"opening_hours\"] = hours\n\n        yield GeojsonPointItem(**properties)\n\n    def parse_city_stores(self, response):\n        stores = response.xpath('//div[@class=\"each-store\"]')\n\n        for store in stores:\n\n            direction = store.xpath('normalize-space(.//span[@class=\"store-number\"]/a/@href)').extract_first()\n            if direction:\n                yield scrapy.Request(response.urljoin(direction), callback=self.parse_stores)\n\n    def parse_state(self, response):\n        city_urls = response.xpath('//div[@class=\"states\"]/ul/li/a/@href').extract()\n        for path in city_urls:\n            yield scrapy.Request(response.urljoin(path), callback=self.parse_city_stores)\n\n    def parse(self, response):\n        urls = response.xpath('//div[@class=\"states\"]/ul/li/a/@href').extract()\n        for path in urls:\n            yield scrapy.Request(response.urljoin(path), callback=self.parse_state)\n", "path": "locations/spiders/cvs.py"}]}