Repository: alltheplaces/alltheplaces

Issue:
therange.co.uk
https://www.therange.co.uk/stores/


Discussion:
How do I self-assign this?
![image](https://user-images.githubusercontent.com/9920034/34086535-58a1141a-e351-11e7-84a4-f45acd29e44b.png)
press here
Not an option for me, can you add me as a contributor?
@evanmosseri I invited you a couple hours ago.
@iandees I never got an invite, are you sure that you added me as a contributor? I am not on the contributor list: https://github.com/alltheplaces/alltheplaces/graphs/contributors
@evanmosseri check your email (including spam). Or go to https://github.com/orgs/alltheplaces and you should be able to accept the invite.
Ah, sorry I don't usually use that email, got it. 
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/iceland_foods.py b/locations/spiders/iceland_foods.py
--- a/locations/spiders/iceland_foods.py
+++ b/locations/spiders/iceland_foods.py
@@ -28,7 +28,7 @@ def parse_store_page(self, response):
                 store = json.loads( s )
 
                 # Extract store name from URL
-                store_name = unquote(response.url.split('StoreName=')[1])#.replace('%20', ' ')
+                store_name = unquote(response.url.split('StoreName=')[1])
 
                 # Because country is not always set in address field, guess country from name
                 store_country = 'Ireland' if 'IRELAND ' in store_name else 'UK'
diff --git a/locations/spiders/therange.py b/locations/spiders/therange.py
new file mode 100644
--- /dev/null
+++ b/locations/spiders/therange.py
@@ -0,0 +1,77 @@
+# -*- coding: utf-8 -*-
+import scrapy
+import json
+import re
+from urllib.parse import unquote
+
+from locations.items import GeojsonPointItem
+
+
+class TheRangeSpider(scrapy.Spider):
+    name = "therange"
+    item_attributes = { 'brand': "The Range" }
+    allowed_domains = ['www.therange.co.uk']
+    start_urls = (
+        'https://www.therange.co.uk/stores/',
+    )
+
+    # Stores catalog has a JS array with store coordinates
+    store_to_geo = {}
+
+    # Extracts store's data from an individual store page
+    def parse_store_page(self, response):
+        response.selector.remove_namespaces()
+
+        # One of the <script> tags contains a JSON object with store information
+        scripts = response.css('script').xpath('./text()').getall()
+
+        for s in scripts:
+            if 'Store' in s and 'schema.org' in s:
+
+                try:
+                    # Get a JS object with store information
+                    store = json.loads( s )
+                    
+                    properties = {
+                        'name': store['name'],
+                        'ref': store['name'],
+                        'website': response.url,
+                        'postcode': store['address']['postalCode'],
+                        'city': store['address']['addressLocality'],
+                        'country': store['address']['addressCountry'],
+                        'street': store['address']['streetAddress'],
+                        'phone': store['telephone'],
+                        'lat': self.store_to_geo[ store['name'].split(':')[1].strip() ][0],
+                        'lon': self.store_to_geo[ store['name'].split(':')[1].strip() ][1]
+                    }
+
+                    yield GeojsonPointItem(**properties)
+
+                except:
+                    return
+
+
+    def parse(self, response):
+        response.selector.remove_namespaces()
+
+        # Create a crosswalk dictionary { "Store": [lat, lon], ... } from JS
+        scripts = response.css('script').xpath('./text()').getall()
+        
+        for s in scripts:
+            if 'initStoreFinder()' in s:
+
+                # Extract markers array as a string
+                markers_str = s.split('var markers = [')[1].split('];')[0].strip()
+
+                # Turn the string into a list of individual store strings "Store,Lat,Lon"
+                markers = markers_str.replace('[', '').replace('\n', '').split('],')[:-1]
+                
+                # Save data into store_to_geo class variable
+                for marker in markers:
+                    self.store_to_geo[marker.split(',')[0][1:-1]] = [
+                        float(marker.split(',')[1]),
+                        float(marker.split(',')[2])
+                    ]
+
+        for store in response.css('#storelist li a::attr(href)').getall():
+            yield scrapy.Request( response.urljoin(store) , callback=self.parse_store_page)


Test patch: