We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Spider target_au is broken
During the global build at 2021-05-26-14-42-23, spider **target_au** failed with **0 features** and **16 errors**.

Here's [the log](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/logs/target_au.log) and [the output](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/target_au.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/target_au.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/target_au.py`
Content:
```
1 import scrapy
2 
3 from locations.hours import OpeningHours
4 from locations.items import GeojsonPointItem
5 
6 
7 class TargetAUSpider(scrapy.Spider):
8     name = "target_au"
9     item_attributes = { 'brand': "Target", 'brand_wikidata': "Q7685854" }
10     allowed_domains = ["target.com.au"]
11     states = ["nsw","vic","qld","nt", "act", "sa", "tas", "wa"]
12     headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0",
13                 "Referer": "https://www.target.com.au/store-finder"}
14 
15     custom_settings = {'DOWNLOAD_DELAY' : 0.5,}
16 
17     def start_requests(self):
18         url = "https://www.target.com.au/store-finder/state/{}"
19         for state in self.states:
20             yield scrapy.Request(url.format(state),headers=self.headers, callback=self.parse)
21 
22 
23     def parse(self, response):
24         store_links = response.xpath('//a[@class="table-tap-canonical"]/@href').getall()
25         for link in store_links:
26             yield scrapy.Request(response.urljoin(link), callback=self.parse_store, headers=self.headers)
27 
28     def _parse_hour_str(self, hour_string):
29         time_, am_pm = tuple(hour_string.split(" "))
30         hour, min = tuple(time_.split(":"))
31         hour = int(hour)
32         if am_pm == "PM":
33             hour += 12
34         return f"{hour}:{min}"
35 
36     def parse_hours(self, hours_node):
37         opening_hours = OpeningHours()
38         days = hours_node.xpath(".//dt/text()").getall()
39         hours = hours_node.xpath(".//dd/text()").getall()
40         for idx, day in enumerate(days):
41             store_hours = hours[idx]
42             if "–" not in store_hours or ":" not in store_hours:
43                 continue
44             parts = store_hours.strip().split(" – ")
45             open_time = self._parse_hour_str(parts[0])
46             close_time = self._parse_hour_str(parts[1])
47             opening_hours.add_range(day[0:2], open_time, close_time)
48         
49         return opening_hours.as_opening_hours()
50 
51 
52 
53     def parse_store(self, response):
54         store_name = response.xpath("//h4/text()").get().replace("Target – ","")
55         address_header = response.xpath("//span[@itemprop='streetAddress']/strong/text()").get()
56         address = " ".join(response.xpath("//span[@itemprop='streetAddress']/text()").getall()).strip()
57         if address_header:
58             address = address_header + " " + address
59         locality = response.xpath("//span[@itemprop='addressLocality']/text()").get()
60         region = response.xpath("//span[@itemprop='addressRegion']/text()").get()
61         post_code = response.xpath("//span[@itemprop='postalCode']/text()").get()
62         phone_number = response.xpath("//span[@itemprop='telephone']/text()").get()
63         hours_section = response.xpath("(//dl)[1]")[0]
64         opening_hours = self.parse_hours(hours_section)
65         lat = response.xpath("//div[@data-embedded-json='store-content-data']//@data-lat").get()
66         lon = response.xpath("//div[@data-embedded-json='store-content-data']//@data-lng").get()
67 
68         yield GeojsonPointItem(lat=lat,
69                                 lon=lon,
70                                 name=store_name,
71                                 addr_full=address,
72                                 city=locality,
73                                 state=region,
74                                 postcode=post_code,
75                                 country="AU",
76                                 phone=phone_number,
77                                 website=response.url,
78                                 opening_hours=opening_hours,
79                                 ref=response.url.split("/")[-1])  
80
```
--- 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/target_au.py b/locations/spiders/target_au.py
--- a/locations/spiders/target_au.py
+++ b/locations/spiders/target_au.py
@@ -26,6 +26,8 @@
             yield scrapy.Request(response.urljoin(link), callback=self.parse_store, headers=self.headers)
 
     def _parse_hour_str(self, hour_string):
+        if hour_string == "Midnight":
+            return self._parse_hour_str("12:00 AM")
         time_, am_pm = tuple(hour_string.split(" "))
         hour, min = tuple(time_.split(":"))
         hour = int(hour)

{"golden_diff": "diff --git a/locations/spiders/target_au.py b/locations/spiders/target_au.py\n--- a/locations/spiders/target_au.py\n+++ b/locations/spiders/target_au.py\n@@ -26,6 +26,8 @@\n             yield scrapy.Request(response.urljoin(link), callback=self.parse_store, headers=self.headers)\n \n     def _parse_hour_str(self, hour_string):\n+        if hour_string == \"Midnight\":\n+            return self._parse_hour_str(\"12:00 AM\")\n         time_, am_pm = tuple(hour_string.split(\" \"))\n         hour, min = tuple(time_.split(\":\"))\n         hour = int(hour)\n", "issue": "Spider target_au is broken\nDuring the global build at 2021-05-26-14-42-23, spider **target_au** failed with **0 features** and **16 errors**.\n\nHere's [the log](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/logs/target_au.log) and [the output](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/target_au.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/target_au.geojson))\n", "before_files": [{"content": "import scrapy\n\nfrom locations.hours import OpeningHours\nfrom locations.items import GeojsonPointItem\n\n\nclass TargetAUSpider(scrapy.Spider):\n    name = \"target_au\"\n    item_attributes = { 'brand': \"Target\", 'brand_wikidata': \"Q7685854\" }\n    allowed_domains = [\"target.com.au\"]\n    states = [\"nsw\",\"vic\",\"qld\",\"nt\", \"act\", \"sa\", \"tas\", \"wa\"]\n    headers = {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0\",\n                \"Referer\": \"https://www.target.com.au/store-finder\"}\n\n    custom_settings = {'DOWNLOAD_DELAY' : 0.5,}\n\n    def start_requests(self):\n        url = \"https://www.target.com.au/store-finder/state/{}\"\n        for state in self.states:\n            yield scrapy.Request(url.format(state),headers=self.headers, callback=self.parse)\n\n\n    def parse(self, response):\n        store_links = response.xpath('//a[@class=\"table-tap-canonical\"]/@href').getall()\n        for link in store_links:\n            yield scrapy.Request(response.urljoin(link), callback=self.parse_store, headers=self.headers)\n\n    def _parse_hour_str(self, hour_string):\n        time_, am_pm = tuple(hour_string.split(\" \"))\n        hour, min = tuple(time_.split(\":\"))\n        hour = int(hour)\n        if am_pm == \"PM\":\n            hour += 12\n        return f\"{hour}:{min}\"\n\n    def parse_hours(self, hours_node):\n        opening_hours = OpeningHours()\n        days = hours_node.xpath(\".//dt/text()\").getall()\n        hours = hours_node.xpath(\".//dd/text()\").getall()\n        for idx, day in enumerate(days):\n            store_hours = hours[idx]\n            if \"\u2013\" not in store_hours or \":\" not in store_hours:\n                continue\n            parts = store_hours.strip().split(\" \u2013 \")\n            open_time = self._parse_hour_str(parts[0])\n            close_time = self._parse_hour_str(parts[1])\n            opening_hours.add_range(day[0:2], open_time, close_time)\n        \n        return opening_hours.as_opening_hours()\n\n\n\n    def parse_store(self, response):\n        store_name = response.xpath(\"//h4/text()\").get().replace(\"Target \u2013 \",\"\")\n        address_header = response.xpath(\"//span[@itemprop='streetAddress']/strong/text()\").get()\n        address = \" \".join(response.xpath(\"//span[@itemprop='streetAddress']/text()\").getall()).strip()\n        if address_header:\n            address = address_header + \" \" + address\n        locality = response.xpath(\"//span[@itemprop='addressLocality']/text()\").get()\n        region = response.xpath(\"//span[@itemprop='addressRegion']/text()\").get()\n        post_code = response.xpath(\"//span[@itemprop='postalCode']/text()\").get()\n        phone_number = response.xpath(\"//span[@itemprop='telephone']/text()\").get()\n        hours_section = response.xpath(\"(//dl)[1]\")[0]\n        opening_hours = self.parse_hours(hours_section)\n        lat = response.xpath(\"//div[@data-embedded-json='store-content-data']//@data-lat\").get()\n        lon = response.xpath(\"//div[@data-embedded-json='store-content-data']//@data-lng\").get()\n\n        yield GeojsonPointItem(lat=lat,\n                                lon=lon,\n                                name=store_name,\n                                addr_full=address,\n                                city=locality,\n                                state=region,\n                                postcode=post_code,\n                                country=\"AU\",\n                                phone=phone_number,\n                                website=response.url,\n                                opening_hours=opening_hours,\n                                ref=response.url.split(\"/\")[-1])  \n", "path": "locations/spiders/target_au.py"}], "after_files": [{"content": "import scrapy\n\nfrom locations.hours import OpeningHours\nfrom locations.items import GeojsonPointItem\n\n\nclass TargetAUSpider(scrapy.Spider):\n    name = \"target_au\"\n    item_attributes = { 'brand': \"Target\", 'brand_wikidata': \"Q7685854\" }\n    allowed_domains = [\"target.com.au\"]\n    states = [\"nsw\",\"vic\",\"qld\",\"nt\", \"act\", \"sa\", \"tas\", \"wa\"]\n    headers = {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0\",\n                \"Referer\": \"https://www.target.com.au/store-finder\"}\n\n    custom_settings = {'DOWNLOAD_DELAY' : 0.5,}\n\n    def start_requests(self):\n        url = \"https://www.target.com.au/store-finder/state/{}\"\n        for state in self.states:\n            yield scrapy.Request(url.format(state),headers=self.headers, callback=self.parse)\n\n\n    def parse(self, response):\n        store_links = response.xpath('//a[@class=\"table-tap-canonical\"]/@href').getall()\n        for link in store_links:\n            yield scrapy.Request(response.urljoin(link), callback=self.parse_store, headers=self.headers)\n\n    def _parse_hour_str(self, hour_string):\n        if hour_string == \"Midnight\":\n            return self._parse_hour_str(\"12:00 AM\")\n        time_, am_pm = tuple(hour_string.split(\" \"))\n        hour, min = tuple(time_.split(\":\"))\n        hour = int(hour)\n        if am_pm == \"PM\":\n            hour += 12\n        return f\"{hour}:{min}\"\n\n    def parse_hours(self, hours_node):\n        opening_hours = OpeningHours()\n        days = hours_node.xpath(\".//dt/text()\").getall()\n        hours = hours_node.xpath(\".//dd/text()\").getall()\n        for idx, day in enumerate(days):\n            store_hours = hours[idx]\n            if \"\u2013\" not in store_hours or \":\" not in store_hours:\n                continue\n            parts = store_hours.strip().split(\" \u2013 \")\n            open_time = self._parse_hour_str(parts[0])\n            close_time = self._parse_hour_str(parts[1])\n            opening_hours.add_range(day[0:2], open_time, close_time)\n        \n        return opening_hours.as_opening_hours()\n\n\n\n    def parse_store(self, response):\n        store_name = response.xpath(\"//h4/text()\").get().replace(\"Target \u2013 \",\"\")\n        address_header = response.xpath(\"//span[@itemprop='streetAddress']/strong/text()\").get()\n        address = \" \".join(response.xpath(\"//span[@itemprop='streetAddress']/text()\").getall()).strip()\n        if address_header:\n            address = address_header + \" \" + address\n        locality = response.xpath(\"//span[@itemprop='addressLocality']/text()\").get()\n        region = response.xpath(\"//span[@itemprop='addressRegion']/text()\").get()\n        post_code = response.xpath(\"//span[@itemprop='postalCode']/text()\").get()\n        phone_number = response.xpath(\"//span[@itemprop='telephone']/text()\").get()\n        hours_section = response.xpath(\"(//dl)[1]\")[0]\n        opening_hours = self.parse_hours(hours_section)\n        lat = response.xpath(\"//div[@data-embedded-json='store-content-data']//@data-lat\").get()\n        lon = response.xpath(\"//div[@data-embedded-json='store-content-data']//@data-lng\").get()\n\n        yield GeojsonPointItem(lat=lat,\n                                lon=lon,\n                                name=store_name,\n                                addr_full=address,\n                                city=locality,\n                                state=region,\n                                postcode=post_code,\n                                country=\"AU\",\n                                phone=phone_number,\n                                website=response.url,\n                                opening_hours=opening_hours,\n                                ref=response.url.split(\"/\")[-1])  \n", "path": "locations/spiders/target_au.py"}]}