Repository: alltheplaces/alltheplaces

Issue:
WineTime (UA) (shop/wine)
### Brand name

WINETIME

Ukrainian chain of food and wine markets

### Wikidata ID

Q116698397
https://www.wikidata.org/wiki/Q116698397
https://www.wikidata.org/wiki/Special:EntityData/Q116698397.json

### Store finder url(s)

https://winetime.ua/sitemap.xml
https://winetime.ua/store/vinnytsia/

Official Url(s): https://winetime.ua/
- [x] I have run the below and if anything in generated, added it.
- [x] I have manually checked for a storefinder
- [ ] This is not a manufacturer listing outlets operating under their own brands / this will not create duplicates
`pipenv run scrapy sf --brand-wikidata=Q116698397 https://winetime.ua/`
```
```

----



Discussion:

Resolving patch:
diff --git a/locations/spiders/winetime_ua.py b/locations/spiders/winetime_ua.py
new file mode 100644
--- /dev/null
+++ b/locations/spiders/winetime_ua.py
@@ -0,0 +1,60 @@
+import re
+from hashlib import sha1
+
+from scrapy.linkextractors import LinkExtractor
+from scrapy.spiders import CrawlSpider, Rule
+
+from locations.hours import DAYS, OpeningHours
+from locations.items import Feature
+
+
+class WINETIMEUASpider(CrawlSpider):
+    name = "winetime_ua"
+    item_attributes = {"brand": "WINETIME", "brand_wikidata": "Q116698397"}
+    allowed_domains = ["winetime.ua"]
+    start_urls = ["https://winetime.ua/store/vinnytsia/"]
+    rules = [
+        Rule(
+            LinkExtractor(
+                allow=r"^https:\/\/winetime\.ua\/store\/[^/]+\/$",
+                restrict_xpaths='//div[contains(@class, "city-choise")]/ul/li/a',
+            ),
+            callback="parse",
+        )
+    ]
+
+    def parse_start_url(self, response):
+        return self.parse(response)
+
+    def parse(self, response):
+        for location in response.xpath('//div[contains(@class, "city_content")]'):
+            location_details = location.xpath('.//div[@class="block_content"]')
+            properties = {
+                "name": location_details.xpath("./h3/text()").get("").strip(),
+                "lat": location.xpath('.//p[@class="latitude"]/text()').get("").strip(),
+                "lon": location.xpath('.//p[@class="longitude"]/text()').get("").strip(),
+                "street_address": re.sub(
+                    r"Адреса\s+:\s+", "", location_details.xpath('./div[contains(text(), "Адреса")]/text()').get("")
+                ).strip(),
+                "city": response.xpath('//h1[@class="title"]/text()').get("").strip(),
+                "phone": re.sub(
+                    r"Телефон\s+:\s+", "", location_details.xpath('./div[contains(text(), "Телефон")]/text()').get("")
+                ).strip(),
+                "website": response.url,
+                "opening_hours": OpeningHours(),
+            }
+            location_key = properties["street_address"] + properties["city"]
+            properties["ref"] = sha1(location_key.encode("UTF-8")).hexdigest()
+            properties["opening_hours"].add_days_range(
+                DAYS,
+                *map(
+                    str.strip,
+                    re.sub(
+                        r"Час роботи\s+:\s+",
+                        "",
+                        location_details.xpath('./div[contains(text(), "Час роботи")]/text()').get(""),
+                    ).split("-", 1),
+                ),
+                "%H:%M",
+            )
+            yield Feature(**properties)


Test patch: