We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Spider subway is broken
During the global build at 2021-09-15-14-42-44, spider **subway** failed with **31396 features** and **22 errors**.

Here's [the log](https://data.alltheplaces.xyz/runs/2021-09-15-14-42-44/logs/subway.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-09-15-14-42-44/output/subway.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-09-15-14-42-44/output/subway.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/subway.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 import scrapy
3 from locations.items import GeojsonPointItem
4 from locations.hours import OpeningHours
5 
6 from urllib.parse import urlparse
7 import json
8 
9 
10 DAY_MAPPING = {
11     "MONDAY": "Mo",
12     "TUESDAY": "Tu",
13     "WEDNESDAY": "We",
14     "THURSDAY": "Th",
15     "FRIDAY": "Fr",
16     "SATURDAY": "Sa",
17     "SUNDAY": "Su",
18 }
19 
20 
21 class SubwaySpider(scrapy.Spider):
22     name = "subway"
23     item_attributes = {"name": "Subway", "brand": "Subway", "brand_wikidata": "Q244457"}
24     allowed_domains = ["restaurants.subway.com"]
25     start_urls = ["https://restaurants.subway.com/"]
26 
27     link_extractor = scrapy.linkextractors.LinkExtractor(
28         restrict_css=".Directory-listLinks, .Directory-listTeasers"
29     )
30 
31     def parse(self, response):
32         for link in self.link_extractor.extract_links(response):
33             yield scrapy.Request(link.url)
34 
35         js = response.xpath('//script[@class="js-hours-config"]/text()').get()
36         if js:
37             yield from self.parse_restaurant(json.loads(js))
38 
39     def parse_restaurant(self, js):
40         # Note: Of the five different coordinate fields, this is the one that always exists
41         lat_long = js["profile"]["yextDisplayCoordinate"]
42         website = urlparse(js["profile"]["websiteUrl"])._replace(query="").geturl()
43         properties = {
44             "lat": lat_long["lat"],
45             "lon": lat_long["long"],
46             "ref": js["profile"]["meta"]["id"],
47             "addr_full": js["profile"]["address"]["line1"],
48             "extras": {
49                 "addr:unit": js["profile"]["address"]["line2"],
50                 # Note: line3 is always null
51                 "loc_name": js["profile"]["address"]["extraDescription"],
52             },
53             "city": js["profile"]["address"]["city"],
54             "state": js["profile"]["address"]["region"],
55             "postcode": js["profile"]["address"]["postalCode"],
56             "country": js["profile"]["address"]["countryCode"],
57             "phone": js["profile"].get("mainPhone", {}).get("number"),
58             "opening_hours": self.parse_hours(js["profile"]["hours"]["normalHours"]),
59             "website": website,
60         }
61         yield GeojsonPointItem(**properties)
62 
63     def parse_hours(self, hours_json):
64         opening_hours = OpeningHours()
65         for date in hours_json:
66             day = DAY_MAPPING[date["day"]]
67             for interval in date["intervals"]:
68                 start_hr, start_min = divmod(interval["start"], 100)
69                 end_hr, end_min = divmod(interval["end"], 100)
70                 opening_hours.add_range(
71                     day, f"{start_hr}:{start_min}", f"{end_hr}:{end_min}"
72                 )
73         return opening_hours.as_opening_hours()
74
```
--- 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/subway.py b/locations/spiders/subway.py
--- a/locations/spiders/subway.py
+++ b/locations/spiders/subway.py
@@ -39,7 +39,9 @@
     def parse_restaurant(self, js):
         # Note: Of the five different coordinate fields, this is the one that always exists
         lat_long = js["profile"]["yextDisplayCoordinate"]
-        website = urlparse(js["profile"]["websiteUrl"])._replace(query="").geturl()
+        website = ""
+        if 'websiteUrl' in js["profile"]:
+            website = urlparse(js["profile"]["websiteUrl"])._replace(query="").geturl()
         properties = {
             "lat": lat_long["lat"],
             "lon": lat_long["long"],

{"golden_diff": "diff --git a/locations/spiders/subway.py b/locations/spiders/subway.py\n--- a/locations/spiders/subway.py\n+++ b/locations/spiders/subway.py\n@@ -39,7 +39,9 @@\n     def parse_restaurant(self, js):\n         # Note: Of the five different coordinate fields, this is the one that always exists\n         lat_long = js[\"profile\"][\"yextDisplayCoordinate\"]\n-        website = urlparse(js[\"profile\"][\"websiteUrl\"])._replace(query=\"\").geturl()\n+        website = \"\"\n+        if 'websiteUrl' in js[\"profile\"]:\n+            website = urlparse(js[\"profile\"][\"websiteUrl\"])._replace(query=\"\").geturl()\n         properties = {\n             \"lat\": lat_long[\"lat\"],\n             \"lon\": lat_long[\"long\"],\n", "issue": "Spider subway is broken\nDuring the global build at 2021-09-15-14-42-44, spider **subway** failed with **31396 features** and **22 errors**.\n\nHere's [the log](https://data.alltheplaces.xyz/runs/2021-09-15-14-42-44/logs/subway.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-09-15-14-42-44/output/subway.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-09-15-14-42-44/output/subway.geojson))\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nimport scrapy\nfrom locations.items import GeojsonPointItem\nfrom locations.hours import OpeningHours\n\nfrom urllib.parse import urlparse\nimport json\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 SubwaySpider(scrapy.Spider):\n    name = \"subway\"\n    item_attributes = {\"name\": \"Subway\", \"brand\": \"Subway\", \"brand_wikidata\": \"Q244457\"}\n    allowed_domains = [\"restaurants.subway.com\"]\n    start_urls = [\"https://restaurants.subway.com/\"]\n\n    link_extractor = scrapy.linkextractors.LinkExtractor(\n        restrict_css=\".Directory-listLinks, .Directory-listTeasers\"\n    )\n\n    def parse(self, response):\n        for link in self.link_extractor.extract_links(response):\n            yield scrapy.Request(link.url)\n\n        js = response.xpath('//script[@class=\"js-hours-config\"]/text()').get()\n        if js:\n            yield from self.parse_restaurant(json.loads(js))\n\n    def parse_restaurant(self, js):\n        # Note: Of the five different coordinate fields, this is the one that always exists\n        lat_long = js[\"profile\"][\"yextDisplayCoordinate\"]\n        website = urlparse(js[\"profile\"][\"websiteUrl\"])._replace(query=\"\").geturl()\n        properties = {\n            \"lat\": lat_long[\"lat\"],\n            \"lon\": lat_long[\"long\"],\n            \"ref\": js[\"profile\"][\"meta\"][\"id\"],\n            \"addr_full\": js[\"profile\"][\"address\"][\"line1\"],\n            \"extras\": {\n                \"addr:unit\": js[\"profile\"][\"address\"][\"line2\"],\n                # Note: line3 is always null\n                \"loc_name\": js[\"profile\"][\"address\"][\"extraDescription\"],\n            },\n            \"city\": js[\"profile\"][\"address\"][\"city\"],\n            \"state\": js[\"profile\"][\"address\"][\"region\"],\n            \"postcode\": js[\"profile\"][\"address\"][\"postalCode\"],\n            \"country\": js[\"profile\"][\"address\"][\"countryCode\"],\n            \"phone\": js[\"profile\"].get(\"mainPhone\", {}).get(\"number\"),\n            \"opening_hours\": self.parse_hours(js[\"profile\"][\"hours\"][\"normalHours\"]),\n            \"website\": website,\n        }\n        yield GeojsonPointItem(**properties)\n\n    def parse_hours(self, hours_json):\n        opening_hours = OpeningHours()\n        for date in hours_json:\n            day = DAY_MAPPING[date[\"day\"]]\n            for interval in date[\"intervals\"]:\n                start_hr, start_min = divmod(interval[\"start\"], 100)\n                end_hr, end_min = divmod(interval[\"end\"], 100)\n                opening_hours.add_range(\n                    day, f\"{start_hr}:{start_min}\", f\"{end_hr}:{end_min}\"\n                )\n        return opening_hours.as_opening_hours()\n", "path": "locations/spiders/subway.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nimport scrapy\nfrom locations.items import GeojsonPointItem\nfrom locations.hours import OpeningHours\n\nfrom urllib.parse import urlparse\nimport json\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 SubwaySpider(scrapy.Spider):\n    name = \"subway\"\n    item_attributes = {\"name\": \"Subway\", \"brand\": \"Subway\", \"brand_wikidata\": \"Q244457\"}\n    allowed_domains = [\"restaurants.subway.com\"]\n    start_urls = [\"https://restaurants.subway.com/\"]\n\n    link_extractor = scrapy.linkextractors.LinkExtractor(\n        restrict_css=\".Directory-listLinks, .Directory-listTeasers\"\n    )\n\n    def parse(self, response):\n        for link in self.link_extractor.extract_links(response):\n            yield scrapy.Request(link.url)\n\n        js = response.xpath('//script[@class=\"js-hours-config\"]/text()').get()\n        if js:\n            yield from self.parse_restaurant(json.loads(js))\n\n    def parse_restaurant(self, js):\n        # Note: Of the five different coordinate fields, this is the one that always exists\n        lat_long = js[\"profile\"][\"yextDisplayCoordinate\"]\n        website = \"\"\n        if 'websiteUrl' in js[\"profile\"]:\n            website = urlparse(js[\"profile\"][\"websiteUrl\"])._replace(query=\"\").geturl()\n        properties = {\n            \"lat\": lat_long[\"lat\"],\n            \"lon\": lat_long[\"long\"],\n            \"ref\": js[\"profile\"][\"meta\"][\"id\"],\n            \"addr_full\": js[\"profile\"][\"address\"][\"line1\"],\n            \"extras\": {\n                \"addr:unit\": js[\"profile\"][\"address\"][\"line2\"],\n                # Note: line3 is always null\n                \"loc_name\": js[\"profile\"][\"address\"][\"extraDescription\"],\n            },\n            \"city\": js[\"profile\"][\"address\"][\"city\"],\n            \"state\": js[\"profile\"][\"address\"][\"region\"],\n            \"postcode\": js[\"profile\"][\"address\"][\"postalCode\"],\n            \"country\": js[\"profile\"][\"address\"][\"countryCode\"],\n            \"phone\": js[\"profile\"].get(\"mainPhone\", {}).get(\"number\"),\n            \"opening_hours\": self.parse_hours(js[\"profile\"][\"hours\"][\"normalHours\"]),\n            \"website\": website,\n        }\n        yield GeojsonPointItem(**properties)\n\n    def parse_hours(self, hours_json):\n        opening_hours = OpeningHours()\n        for date in hours_json:\n            day = DAY_MAPPING[date[\"day\"]]\n            for interval in date[\"intervals\"]:\n                start_hr, start_min = divmod(interval[\"start\"], 100)\n                end_hr, end_min = divmod(interval[\"end\"], 100)\n                opening_hours.add_range(\n                    day, f\"{start_hr}:{start_min}\", f\"{end_hr}:{end_min}\"\n                )\n        return opening_hours.as_opening_hours()\n", "path": "locations/spiders/subway.py"}]}