prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Spider albert_heijn is broken
  During the global build at 2021-06-02-14-42-40, spider **albert_heijn** failed with **0 features** and **0 errors**.
  
  Here's [the log](https://data.alltheplaces.xyz/runs/2021-06-02-14-42-40/logs/albert_heijn.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-06-02-14-42-40/output/albert_heijn.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-06-02-14-42-40/output/albert_heijn.geojson))
  
  </issue>
  <code>
  [start of locations/spiders/albert_heijn.py]
  1 # -*- coding: utf-8 -*-
  2 import scrapy
  3 from locations.items import GeojsonPointItem
  4 import json
  5 
  6 class AlbertHeijnSpider(scrapy.Spider):
  7     name = 'albert_heijn'
  8     item_attributes = {'brand': "Albert Heijn"}
  9     allowed_domains = ['www.ah.nl']
  10 
  11     def start_requests(self):
  12         url = 'https://www.ah.nl/data/winkelinformatie/winkels/json'
  13         yield scrapy.Request(url, callback=self.parse)
  14 
  15     def parse(self, response):
  16         stores = json.loads(response.body_as_unicode())
  17         for store in stores['stores']:
  18             try:
  19                 phone_number = store['phoneNumber']
  20             except:
  21                 phone_number = ""
  22             yield GeojsonPointItem(
  23                 lat=store['lat'],
  24                 lon=store['lng'],
  25                 addr_full="%s %s" % (store['street'], store["housenr"]),
  26                 city=store['city'],
  27                 phone=phone_number,
  28                 state="",
  29                 postcode=store['zip'],
  30                 ref=store['no'],
  31                 country="Netherlands",
  32                 website="https://www.ah.nl/winkel/albert-heijn/%s/%s/%s" % (store['city'], store['street'], store['no'])
  33             )
  34
  [end of locations/spiders/albert_heijn.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/locations/spiders/albert_heijn.py b/locations/spiders/albert_heijn.py
  --- a/locations/spiders/albert_heijn.py
  +++ b/locations/spiders/albert_heijn.py
  @@ -1,33 +1,53 @@
   # -*- coding: utf-8 -*-
  +import json
  +import re
  +
   import scrapy
  +
  +from locations.hours import OpeningHours
   from locations.items import GeojsonPointItem
  -import json
   
  -class AlbertHeijnSpider(scrapy.Spider):
  -    name = 'albert_heijn'
  -    item_attributes = {'brand': "Albert Heijn"}
  -    allowed_domains = ['www.ah.nl']
   
  -    def start_requests(self):
  -        url = 'https://www.ah.nl/data/winkelinformatie/winkels/json'
  -        yield scrapy.Request(url, callback=self.parse)
  +class AlbertHeijnSpider(scrapy.Spider):
  +    name = "albert_heijn"
  +    item_attributes = {"brand": "Albert Heijn", "brand_wikidata": "Q1653985"}
  +    allowed_domains = ["www.ah.nl", "www.ah.be"]
  +    start_urls = (
  +        "https://www.ah.nl/sitemaps/entities/stores/stores.xml",
  +        "https://www.ah.be/sitemaps/entities/stores/stores.xml",
  +    )
   
       def parse(self, response):
  -        stores = json.loads(response.body_as_unicode())
  -        for store in stores['stores']:
  -            try:
  -                phone_number = store['phoneNumber']
  -            except:
  -                phone_number = ""
  -            yield GeojsonPointItem(
  -                lat=store['lat'],
  -                lon=store['lng'],
  -                addr_full="%s %s" % (store['street'], store["housenr"]),
  -                city=store['city'],
  -                phone=phone_number,
  -                state="",
  -                postcode=store['zip'],
  -                ref=store['no'],
  -                country="Netherlands",
  -                website="https://www.ah.nl/winkel/albert-heijn/%s/%s/%s" % (store['city'], store['street'], store['no'])
  -            )
  +        response.selector.remove_namespaces()
  +        for url in response.xpath("//loc/text()").extract():
  +            if re.search("/winkel/albert-heijn/", url):
  +                yield scrapy.Request(url, callback=self.parse_store)
  +
  +    def parse_store(self, response):
  +        for ldjson in response.xpath(
  +            '//script[@type="application/ld+json"]/text()'
  +        ).extract():
  +            data = json.loads(ldjson)
  +            if data["@type"] != "GroceryStore":
  +                continue
  +
  +            opening_hours = OpeningHours()
  +            for spec in data["openingHoursSpecification"]:
  +                opening_hours.add_range(
  +                    spec["dayOfWeek"][:2], spec["opens"], spec["closes"]
  +                )
  +
  +            properties = {
  +                "ref": response.url,
  +                "website": response.url,
  +                "name": data["name"],
  +                "phone": data["telephone"],
  +                "lat": data["geo"]["latitude"],
  +                "lon": data["geo"]["longitude"],
  +                "addr_full": data["address"]["streetAddress"],
  +                "city": data["address"]["addressLocality"],
  +                "postcode": data["address"]["postalCode"],
  +                "country": data["address"]["addressCountry"],
  +                "opening_hours": opening_hours.as_opening_hours(),
  +            }
  +            yield GeojsonPointItem(**properties)
  
verification_info: {"golden_diff": "diff --git a/locations/spiders/albert_heijn.py b/locations/spiders/albert_heijn.py\n--- a/locations/spiders/albert_heijn.py\n+++ b/locations/spiders/albert_heijn.py\n@@ -1,33 +1,53 @@\n # -*- coding: utf-8 -*-\n+import json\n+import re\n+\n import scrapy\n+\n+from locations.hours import OpeningHours\n from locations.items import GeojsonPointItem\n-import json\n \n-class AlbertHeijnSpider(scrapy.Spider):\n-    name = 'albert_heijn'\n-    item_attributes = {'brand': \"Albert Heijn\"}\n-    allowed_domains = ['www.ah.nl']\n \n-    def start_requests(self):\n-        url = 'https://www.ah.nl/data/winkelinformatie/winkels/json'\n-        yield scrapy.Request(url, callback=self.parse)\n+class AlbertHeijnSpider(scrapy.Spider):\n+    name = \"albert_heijn\"\n+    item_attributes = {\"brand\": \"Albert Heijn\", \"brand_wikidata\": \"Q1653985\"}\n+    allowed_domains = [\"www.ah.nl\", \"www.ah.be\"]\n+    start_urls = (\n+        \"https://www.ah.nl/sitemaps/entities/stores/stores.xml\",\n+        \"https://www.ah.be/sitemaps/entities/stores/stores.xml\",\n+    )\n \n     def parse(self, response):\n-        stores = json.loads(response.body_as_unicode())\n-        for store in stores['stores']:\n-            try:\n-                phone_number = store['phoneNumber']\n-            except:\n-                phone_number = \"\"\n-            yield GeojsonPointItem(\n-                lat=store['lat'],\n-                lon=store['lng'],\n-                addr_full=\"%s %s\" % (store['street'], store[\"housenr\"]),\n-                city=store['city'],\n-                phone=phone_number,\n-                state=\"\",\n-                postcode=store['zip'],\n-                ref=store['no'],\n-                country=\"Netherlands\",\n-                website=\"https://www.ah.nl/winkel/albert-heijn/%s/%s/%s\" % (store['city'], store['street'], store['no'])\n-            )\n+        response.selector.remove_namespaces()\n+        for url in response.xpath(\"//loc/text()\").extract():\n+            if re.search(\"/winkel/albert-heijn/\", url):\n+                yield scrapy.Request(url, callback=self.parse_store)\n+\n+    def parse_store(self, response):\n+        for ldjson in response.xpath(\n+            '//script[@type=\"application/ld+json\"]/text()'\n+        ).extract():\n+            data = json.loads(ldjson)\n+            if data[\"@type\"] != \"GroceryStore\":\n+                continue\n+\n+            opening_hours = OpeningHours()\n+            for spec in data[\"openingHoursSpecification\"]:\n+                opening_hours.add_range(\n+                    spec[\"dayOfWeek\"][:2], spec[\"opens\"], spec[\"closes\"]\n+                )\n+\n+            properties = {\n+                \"ref\": response.url,\n+                \"website\": response.url,\n+                \"name\": data[\"name\"],\n+                \"phone\": data[\"telephone\"],\n+                \"lat\": data[\"geo\"][\"latitude\"],\n+                \"lon\": data[\"geo\"][\"longitude\"],\n+                \"addr_full\": data[\"address\"][\"streetAddress\"],\n+                \"city\": data[\"address\"][\"addressLocality\"],\n+                \"postcode\": data[\"address\"][\"postalCode\"],\n+                \"country\": data[\"address\"][\"addressCountry\"],\n+                \"opening_hours\": opening_hours.as_opening_hours(),\n+            }\n+            yield GeojsonPointItem(**properties)\n", "issue": "Spider albert_heijn is broken\nDuring the global build at 2021-06-02-14-42-40, spider **albert_heijn** failed with **0 features** and **0 errors**.\n\nHere's [the log](https://data.alltheplaces.xyz/runs/2021-06-02-14-42-40/logs/albert_heijn.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-06-02-14-42-40/output/albert_heijn.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-06-02-14-42-40/output/albert_heijn.geojson))\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nimport scrapy\nfrom locations.items import GeojsonPointItem\nimport json\n\nclass AlbertHeijnSpider(scrapy.Spider):\n    name = 'albert_heijn'\n    item_attributes = {'brand': \"Albert Heijn\"}\n    allowed_domains = ['www.ah.nl']\n\n    def start_requests(self):\n        url = 'https://www.ah.nl/data/winkelinformatie/winkels/json'\n        yield scrapy.Request(url, callback=self.parse)\n\n    def parse(self, response):\n        stores = json.loads(response.body_as_unicode())\n        for store in stores['stores']:\n            try:\n                phone_number = store['phoneNumber']\n            except:\n                phone_number = \"\"\n            yield GeojsonPointItem(\n                lat=store['lat'],\n                lon=store['lng'],\n                addr_full=\"%s %s\" % (store['street'], store[\"housenr\"]),\n                city=store['city'],\n                phone=phone_number,\n                state=\"\",\n                postcode=store['zip'],\n                ref=store['no'],\n                country=\"Netherlands\",\n                website=\"https://www.ah.nl/winkel/albert-heijn/%s/%s/%s\" % (store['city'], store['street'], store['no'])\n            )\n", "path": "locations/spiders/albert_heijn.py"}]}