internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: alltheplaces/alltheplaces

Issue:
Barnes and Noble
https://stores.barnesandnoble.com/stores?lng=-97.7429885864258&lat=30.2675895690918&searchText=Austin%2c+TX&storeFilter=all&v=1&view=map


I didn't assign myself on purpose this time. 


Discussion:
Can I assign my self?
If it doesn't have to be approved by @iandees I don't see why not
Yes, you can assign yourself.
@iandees 
I updated Qdoba and Tacobel spider already. Can you check them please?
This issue hasn't been worked on in a while. I'm removing the assignment so others can work on it. If you're still working on it, please reassign yourself and reference a pull request or branch where you're doing your work.

Resolving patch:
diff --git a/locations/spiders/barnesandnoble_college.py b/locations/spiders/barnesandnoble_college.py
new file mode 100644
--- /dev/null
+++ b/locations/spiders/barnesandnoble_college.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+import re
+
+import scrapy
+
+from locations.items import GeojsonPointItem
+
+
+class BarnesNobleCollegeSpider(scrapy.Spider):
+    name = "barnesnoblecollege"
+    item_attributes = {'brand': "Barnes & Noble College" }
+    allowed_domains = ["bncollege.com"]
+    start_urls = (
+        'https://www.bncollege.com/campus-stores/',
+    )
+
+    def parse(self, response):
+        locations = response.xpath('//section[@id="map-results"]//h3')
+        address_data = response.xpath('//div[@class="address"]/p')
+
+        for location, addresses, citypostal in zip(locations, address_data, address_data):
+            name = location.xpath('.//text()').extract_first()
+            address = addresses.xpath('.//text()').extract_first()
+            city_postal = citypostal.xpath('.//text()').extract().pop(-1).strip()
+            try:
+                city_state, postal = re.search(r'\s+(.*)(\d{5})', city_postal).groups()
+                city, state = city_state.split(',')
+            except:
+                continue
+
+            properties = {
+                'ref': name,
+                'name': name,
+                'addr_full': address,
+                'city': city.strip(),
+                'state': state.strip(),
+                'postcode': postal.strip(),
+                'country': "US",
+                'website': response.url
+            }
+
+            yield GeojsonPointItem(**properties)
\ No newline at end of file


Test patch:
Repository: alltheplaces/alltheplaces

Issue:
Kindred Healthcare
https://www.kindredhealthcare.com/sitemap/sitemap.xml


Discussion:

Resolving patch:
diff --git a/locations/spiders/kindred_healthcare.py b/locations/spiders/kindred_healthcare.py
new file mode 100644
--- /dev/null
+++ b/locations/spiders/kindred_healthcare.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+import json
+import re
+
+import scrapy
+
+from locations.items import GeojsonPointItem
+
+
+class KindredHealthcareSpider(scrapy.Spider):
+    name = "kindred_healthcare"
+    item_attributes = {'brand': "Kindred Healthcare"}
+    allowed_domains = ['www.kindredhealthcare.com']
+    start_urls = [
+        'https://www.kindredhealthcare.com/sitemap/sitemap.xml',
+    ]
+    download_delay = 0.3
+
+    def parse_location(self, response):
+        is_location_page = response.xpath('//script[@type="application/ld+json" and contains(text(), "streetAddress")]/text()')
+
+        if is_location_page:
+            data = json.loads(response.xpath('//script[@type="application/ld+json" and contains(text(), "streetAddress")]/text()').extract_first())
+
+            facility_type = data["@type"]
+            if facility_type == 'Hospital':  # Keep refs consistent
+                ref = re.search(r".+/(.+?)/(.+?)/?(?:\.html|$)", response.url).group(1)
+            else:
+                ref = re.search(r'.+/(.+?)/?(?:\.html|$)', response.url).group(1)
+
+            properties = {
+                'name': data["name"],
+                'ref': ref,
+                'addr_full': data["address"]["streetAddress"],
+                'city': data["address"]["addressLocality"],
+                'state': data["address"]["addressRegion"],
+                'postcode': data["address"]["postalCode"],
+                'country': data["address"]["addressCountry"],
+                'phone': data.get("contactPoint", {}).get("telephone"),
+                'website': data.get("url") or response.url,
+                'lat': float(data["geo"]["latitude"]),
+                'lon': float(data["geo"]["longitude"]),
+                'extras': {'facility_type': facility_type}
+            }
+
+            yield GeojsonPointItem(**properties)
+
+    def parse(self, response):
+        response.selector.remove_namespaces()
+        locations = response.xpath('//url/loc/text()[contains(., "locations")]').extract()
+
+        for location_url in locations:
+            # For transitional care hospitals, reduce redundant requests by using just the contact-us pages
+            if "transitional-care-hospitals" in location_url and "contact-us" not in location_url:
+                continue
+            # Do the same thing for the behavioral health pages
+            if "behavioral-health" in location_url and "contact-us" not in location_url:
+                continue
+
+            yield scrapy.Request(location_url, callback=self.parse_location)


Test patch:
Repository: alltheplaces/alltheplaces

Issue:
Medical City Healthcare
https://medicalcityhealthcare.com/locations/


Discussion:

Resolving patch:
diff --git a/locations/spiders/medical_city_healthcare.py b/locations/spiders/medical_city_healthcare.py
new file mode 100644
--- /dev/null
+++ b/locations/spiders/medical_city_healthcare.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+import json
+import re
+
+import scrapy
+
+from locations.items import GeojsonPointItem
+
+
+class MedicalCityHealthcareSpider(scrapy.Spider):
+    name = "medical_city_healthcare"
+    item_attributes = {'brand': 'Medical City Healthcare'}
+    allowed_domains = ['medicalcityhealthcare.com']
+    start_urls = [
+        'https://medicalcityhealthcare.com/locations/',
+    ]
+
+    def parse(self, response):
+        script = response.xpath('//script[contains(text(), "hostLocations")]').extract_first()
+        data = re.search(r"var hostLocations = (.*]);", script).group(1)
+        locations = json.loads(data)
+
+        for location in locations:
+
+            properties = {
+                'ref': location['id'],
+                'name': location['title'],
+                'addr_full': location['address1'],
+                'city': location['city'],
+                'state': location['state'],
+                'postcode': location['zip'],
+                'lat': location['lat'],
+                'lon': location['lng'],
+                'phone': location['phone'],
+                'website': response.url
+            }
+
+            yield GeojsonPointItem(**properties)


Test patch:
Repository: alltheplaces/alltheplaces

Issue:
Juiceland
https://www.juiceland.com/all-locations/


Discussion:

Resolving patch:
diff --git a/locations/spiders/juiceland.py b/locations/spiders/juiceland.py
new file mode 100644
--- /dev/null
+++ b/locations/spiders/juiceland.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+import json
+import re
+
+import scrapy
+
+from locations.items import GeojsonPointItem
+from locations.hours import OpeningHours
+
+
+class JuicelandSpider(scrapy.Spider):
+    name = "juiceland"
+    item_attributes = {'brand': 'JuiceLand'}
+    allowed_domains = ['juiceland.com']
+    start_urls = [
+        'https://www.juiceland.com/all-locations/',
+    ]
+
+    def parse_hours(self, hours):
+        opening_hours = OpeningHours()
+
+        for hour in hours:
+            try:
+                day, open_time, close_time = re.search(r'([A-Za-z]{2})\s([\d:]+)-([\d:]+)', hour).groups()
+            except:
+                continue
+            opening_hours.add_range(day=day, open_time=open_time, close_time=close_time, time_format='%H:%M')
+
+        return opening_hours.as_opening_hours()
+
+
+    def parse_store(self, response):
+        long = response.xpath('//script[contains(text(), "lng")]/text()').re_first(r'lng":"([\d\.\-]+)"')
+        lat = response.xpath('//script[contains(text(), "lng")]/text()').re_first(r'lat":"([\d\.\-]+)"')
+
+        properties = {
+            'ref': response.url,
+            'name': response.xpath('normalize-space(//*[@itemprop="name"]//text())').extract_first(),
+            'addr_full': response.xpath('normalize-space(//span[@itemprop="StreetAddress"]//text())').extract_first(),
+            'city': response.xpath('normalize-space(//span[@itemprop="addressLocality"]//text())').extract_first(),
+            'state': response.xpath('normalize-space(//span[@itemprop="addressRegion"]//text())').extract_first(),
+            'postcode': response.xpath('normalize-space(//span[@itemprop="postalCode"]//text())').extract_first(),
+            'country': 'US',
+            'phone': response.xpath('normalize-space(//span[@itemprop="telephone"]//text())').extract_first(),
+            'website': response.url,
+            'lat': lat,
+            'lon': long
+        }
+
+        hours = self.parse_hours(response.xpath('//*[@itemprop="openingHours"]/@content').extract())
+
+        if hours:
+            properties['opening_hours'] = hours
+        yield GeojsonPointItem(**properties)
+
+    def parse(self, response):
+        for url in response.xpath('//span[@class="store-info"]/a/@href').extract():
+            yield scrapy.Request(response.urljoin(url), callback=self.parse_store)


Test patch:
Repository: alltheplaces/alltheplaces

Issue:
Caliber Home Loans
https://www.caliberhomeloans.com/loan-consultant/#state


Discussion:

Resolving patch:
diff --git a/locations/spiders/caliber_home_loans.py b/locations/spiders/caliber_home_loans.py
new file mode 100644
--- /dev/null
+++ b/locations/spiders/caliber_home_loans.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+import json
+
+import scrapy
+
+from locations.items import GeojsonPointItem
+
+STATES = ['AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'GA',
+          'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD',
+          'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ',
+          'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC',
+          'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY']
+
+
+class CaliberHomeLoansSpider(scrapy.Spider):
+    name = "caliber_home_loans"
+    item_attributes = {'brand': 'Caliber Home Loans'}
+    allowed_domains = ['www.caliberhomeloans.com']
+    download_delay = 0.3
+
+    def start_requests(self):
+        url = 'https://www.caliberhomeloans.com/Home/BranchList?stateCode={state}&LCSpeciality=all&SpanishSpeaking=no'
+
+        for state in STATES:
+            yield scrapy.http.Request(method='GET', url=url.format(state=state), callback=self.parse_state)
+
+    def parse_state(self, response):
+        data = json.loads(response.text)
+
+        if data:
+            for store in data:
+
+                properties = {
+                    'ref': store['BranchID'],
+                    'name': store['Name'],
+                    'addr_full': store['Address'],
+                    'city': store['City'],
+                    'state': store['State'],
+                    'postcode': store['ZipCode'],
+                    'lat': store['Latitude'],
+                    'lon': store['Longitude'],
+                    'website': response.url
+                }
+
+                yield GeojsonPointItem(**properties)


Test patch:
Repository: alltheplaces/alltheplaces

Issue:
Scooter's Coffee
https://www.scooterscoffee.com/locations


Discussion:

Resolving patch:
diff --git a/locations/spiders/scooters_coffee.py b/locations/spiders/scooters_coffee.py
new file mode 100644
--- /dev/null
+++ b/locations/spiders/scooters_coffee.py
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+import json
+import re
+
+import scrapy
+
+from locations.items import GeojsonPointItem
+from locations.hours import OpeningHours
+
+DAY_MAPPING = {'Mon': 'Mo', 'Tue': 'Tu',
+               'Wed': 'We', 'Thu': 'Th',
+               'Fri': 'Fr', 'Sat': 'Sa',
+               'Sun': 'Su'}
+
+
+class ScootersCoffeeSpider(scrapy.Spider):
+    name = "scooters_coffee"
+    item_attributes = {'brand': "Scooter's Coffee"}
+    allowed_domains = ['code.metalocator.com']
+    download_delay = 0.5
+
+    def start_requests(self):
+        n = 327
+        for store_id in range(1, n+1):
+            url = f'https://code.metalocator.com/index.php?option=com_locator&view=location&tmpl=component&task=load&framed=1&sample_data=undefined&format=json&Itemid=12991&templ[]=item_address_template&lang=&_opt_out=&_urlparams=&distance=NaN&id={store_id}'
+            
+            yield scrapy.Request(url=url, callback=self.parse)
+
+    def parse_hours(self, hours):
+        opening_hours = OpeningHours()
+
+        weekdays = re.findall(r'{(.*?)}', hours)
+        for weekday in weekdays:
+            day, open_close = weekday.split('|')
+            if open_close == 'C':
+                continue
+            else:
+                open_time, close_time = open_close.split('-')
+                opening_hours.add_range(day=DAY_MAPPING[day], open_time=open_time, close_time=close_time, time_format='%I:%M%p')
+
+        return opening_hours.as_opening_hours()
+
+    def parse(self, response):
+        store_data = json.loads(response.text)[0]
+        name = store_data['name']
+        if '*permanently closed' in name.lower():
+            pass
+        else:  # Gather the store details
+
+            properties = {
+                'ref': store_data['id'],
+                'name': store_data['name'].strip(' *COMING SOON'),
+                'addr_full': store_data['address'],
+                'city': store_data['city'],
+                'state': store_data['state'],
+                'postcode': store_data['postalcode'],
+                'country': store_data['country'],
+                'lat': store_data['lat'],
+                'lon': store_data['lng'],
+                'phone': store_data['phone'],
+                'website': response.url
+            }
+
+            hours = store_data.get('hours', '')
+            if hours and hours != '{Sun|C}{Mon|C}{Tue|C}{Wed|C}{Thu|C}{Fri|C}{Sat|C}':
+                store_hours = self.parse_hours(hours)
+                properties["opening_hours"] = store_hours
+
+            yield GeojsonPointItem(**properties)


Test patch:
Repository: alltheplaces/alltheplaces

Issue:
Liberty Mutual
https://www.libertymutual.com/office-sitemap.xml


Discussion:

Resolving patch:
diff --git a/locations/spiders/liberty_mutual.py b/locations/spiders/liberty_mutual.py
new file mode 100644
--- /dev/null
+++ b/locations/spiders/liberty_mutual.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+import json
+import re
+
+import scrapy
+
+from locations.items import GeojsonPointItem
+
+
+class LibertyMutualSpider(scrapy.Spider):
+    name = "liberty_mutual"
+    item_attributes = {'brand': 'Liberty Mutual', 'brand_wikidata': 'Q1516450'}
+    allowed_domains = ['www.libertymutual.com']
+    start_urls = [
+        'http://www.libertymutual.com/office-sitemap.xml',
+    ]
+    download_delay = 10
+    custom_settings = {
+        'USER_AGENT': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36',
+        'CONCURRENT_REQUESTS': '1'
+    }
+
+    def parse_store(self, response):
+        data = re.search(r'<script id="__NEXT_DATA__" type="application/json">(.*?)</script>', response.text)
+
+        if data:
+            json_data = json.loads(data.group(1))
+            store_data = json_data["props"]["pageProps"]["office"]
+            lon, lat = store_data["location"]["coordinates"]
+            properties = {
+                'name': store_data["name"],
+                'ref': store_data["officeCode"],
+                'addr_full': store_data["address"]["street"],
+                'city': store_data["address"]["city"],
+                'state': store_data["address"]["state"]["code"],
+                'postcode': store_data["address"]["zip"],
+                'phone': store_data.get("phones", {}).get("primary", {}).get("number", ''),
+                'website': store_data.get("url") or response.url,
+                'lat': lat,
+                'lon': lon,
+            }
+
+            yield GeojsonPointItem(**properties)
+
+    def parse(self, response):
+        response.selector.remove_namespaces()
+        urls = [x for x in response.xpath('//url/loc/text()').extract() if x.count("/") > 4]
+
+        for url in urls:
+            yield scrapy.Request(url, callback=self.parse_store)


Test patch:
Repository: alltheplaces/alltheplaces

Issue:
Viva Chicken
https://www.vivachicken.com/locations/


Discussion:

Resolving patch:
diff --git a/locations/spiders/viva_chicken.py b/locations/spiders/viva_chicken.py
new file mode 100644
--- /dev/null
+++ b/locations/spiders/viva_chicken.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+import json
+from urllib.parse import urlencode
+
+import scrapy
+
+from locations.items import GeojsonPointItem
+from locations.hours import OpeningHours
+
+BASE_URL = 'https://www.vivachicken.com/wp-admin/admin-ajax.php?'
+DAY_MAPPING = {'sun': 'Su', 'mon': 'Mo', 'tue': 'Tu', 'wed': 'We', 'thu': 'Th', 'fri': 'Fr', 'sat': 'Sa'}
+
+
+class VivaChickenSpider(scrapy.Spider):
+    name = "viva_chicken"
+    item_attributes = {'brand': 'Viva Chicken'}
+    allowed_domains = ['www.vivachicken.com']
+
+    def start_requests(self):
+        params = {
+            'action': 'asl_load_stores',
+            'nonce': 'c1b90b7b16',
+            'load_all': 1,
+            'layout': 1
+        }
+
+        yield scrapy.http.Request(
+            url=BASE_URL + urlencode(params),
+            callback=self.parse,
+            method='GET',
+        )
+
+    def parse_hours(self, hours):
+        opening_hours = OpeningHours()
+        store_hours = json.loads(hours)
+
+        for k, v in DAY_MAPPING.items():
+            open_hours = store_hours.get(k)
+            if not open_hours:
+                continue
+            open_time, close_time = open_hours[0].split(' - ')
+
+            opening_hours.add_range(day=v, open_time=open_time, close_time=close_time,
+                                    time_format='%I:%M %p')
+
+        return opening_hours.as_opening_hours()
+
+    def parse(self, response):
+        locations = json.loads(response.text)
+
+        for location in locations:
+            properties = {
+                'ref': location['id'],
+                'name': location['title'],
+                'addr_full': location['street'],
+                'city': location['city'],
+                'state': location['state'],
+                'postcode': location['postal_code'],
+                'country': location['country'],
+                'lat': location['lat'],
+                'lon': location['lng'],
+                'phone': location['phone'],
+                'website': location['website']
+            }
+
+            hours = location.get('open_hours')
+            if hours:
+                properties['opening_hours'] = self.parse_hours(hours)
+
+            yield GeojsonPointItem(**properties)


Test patch:
Repository: alltheplaces/alltheplaces

Issue:
XL Parts
https://www.xlparts.com/en/locations


Discussion:

Resolving patch:
diff --git a/locations/spiders/xl_parts.py b/locations/spiders/xl_parts.py
new file mode 100644
--- /dev/null
+++ b/locations/spiders/xl_parts.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+import re
+
+from urllib.parse import unquote_plus
+
+import scrapy
+
+from locations.items import GeojsonPointItem
+
+
+class XlPartsSpider(scrapy.Spider):
+    name = "xl_parts"
+    item_attributes = {'brand': 'XL Parts'}
+    allowed_domains = ['www.xlparts.com']
+
+    def start_requests(self):
+        url = 'https://www.xlparts.com/en/locations'
+
+        yield scrapy.http.FormRequest(url=url, method='POST', callback=self.parse)
+
+    def parse(self, response):
+        stores = response.xpath('//div[contains(@id, "store")]')
+        script_data = response.xpath('//script[contains(text(), "var map")]').extract_first()
+
+        for store in stores:
+            store_div = store.xpath('./@id').extract_first()
+            ref = re.search(r'store_div_([0-9]*)', store_div).group(1)
+            name = store.xpath('./h3/text()').extract_first().strip()
+            addr_url = store.xpath('./ul/li/a/@href').extract_first()
+            addr_full = unquote_plus(re.search(r'dir//(.*)', addr_url).group(1))
+            addr_full = " ".join(addr_full.split())
+            phone = store.xpath('./ul/li/span/text()').extract_first()
+
+            # Fetch the coordinates
+            pattern = f"""data\['storeID'\] \= "{store_div}"\;.*?var lat\=([0-9.]*);.*?var longtd=([0-9.-]*);"""
+            lat, lon = re.search(pattern, script_data, flags=re.MULTILINE | re.DOTALL).groups()
+
+            properties = {
+                'ref': ref,
+                'name': name,
+                'addr_full': addr_full,
+                'lat': lat,
+                'lon': lon,
+                'phone': phone,
+                'website': response.url
+            }
+
+            yield GeojsonPointItem(**properties)


Test patch: