In deze vergelijkbare thread ben ik bezig geweest met de website
-tag voor Kruidvat, Trekpleister, en ICI Paris XL. Dit zijn winkels waar de filiaalwebsite afleidbaar is van het filiaalnummer in de ref
van de data.
Er zijn meer winkelketens die dat doen, maar er zijn er ook die delen uit het adres gebruiken, zoals de Lidl dat doet. Bijvoorbeeld:
https://www.lidl.nl/s/nl-NL/filialen/leeuwarden/willem-alexanderplein-1/
Nu is deze data ook herleidbaar als de winkel goed op de kaart staat. Ik heb een script geschreven dat net als de vorige scripts met OSM-data werkt. Voor bovenstaande winkel werkt dat natuurlijk prima.
Maar helaas, zo makkelijk is het nooit.
Er zijn 440 Lild-filialen. Er staan er 430 op de kaart. Het is aannemelijk dat er een of twee missen, en dat de rest in dit rijtje staat.
Ik heb de afgelopen dagen twee dingen gedaan:
- Lidl’s zonder adres aangevuld met het adres.
- Lidl’s met een verkeerd adres verbeterd.
Vooral dat laatste was veel handwerk. Het komt toch best vaak voor dat een mapper de verkeerde adresnode kiest, zeker wanneer er veel adressen zijn binnen een gebouwomtrek. Winkels helpen hier zelf ook niet altijd trouwens, want op de gevel zie je meestal niets.
Deze fouten kon ik opsporen door de gegenereerde URL te testen. Dat is hier nodig, want hoewel je bij de ref
-methode eigenlijk bijna geen fouten kan maken (een voorloopnul negeren was het enige bij Kruidvat), is het hier iets lastiger. Er lijkt namelijk niet één algoritme te zijn dat Lidl toepast. De basis is eenvoudig: maak alles lowercase, vervang spaties en scheidingstekens door -
, en gebruik dit sjabloon:
https://www.lidl.nl/s/nl-NL/filialen/{place}/{street}-{housenumber}/
Maar zo veel uitzonderingen… Met niet-ASCII-tekens wordt verschillend omgesprongen. Soms komen die url-encoded in UTF-8 in de URL (â → %C3%A2
), soms worden ze ‘platgeslagen’ (ë → e
), soms worden ze op z’n Duits uitgeschreven (ä → ae
). Dan moet je dus gewoon gaan testen en de uitzonderingen afvangen.
Ook heel irritant: wanneer een Lidl-vestiging tijdelijk sluit voor verbouwing, dan gaat de filiaalpagina op zwart. Er zijn zo drie vestigingen die ik nu dan maar even negeer.
En dan de monseigneurs en burgemeesters (mgr, burg)…
if place == 's-gravenhage':
place = 'den-haag'
elif place == 's-hertogenbosch':
# Zijn ze in Oeteldonk geen fan van geloof ik...
place = 'den-bosch'
elif postcode == '4904aw':
# Aargh!!
place = 'oosterhout-nb'
elif postcode == '6678aa':
# Aargh!!
place = 'oosterhout-gld'
elif place == 'damwald':
place = 'damw%C3%A2ld'
if street == 'handelplein':
street = 'haendelplein'
elif street == 'tjalk-15':
# Lelystad...
housenumber = '09'
elif street == 'walddyk':
street = 'w%C3%A2lddyk'
elif street == 'mosaique':
street = 'mosa%C3%AFque'
elif street == 'burgemeester-van-loonstraat':
street = 'burg-van-loonstraat'
elif street == 'daniel-goedkoopstraat':
street = 'dani%C3%ABl-goedkoopstraat'
elif street == 'burgemeester-van-hooffln':
street = 'burgemeester-van-hoofflaan'
elif street == 'burgemeester-baumannlaan':
street = 'burg-baumannlaan'
elif street == 'elias-annes-borgerstraat':
street = 'e-a-borgerstraat'
elif street == 'van-oldenbarneveltplein':
street = 'oldenbarneveltplein'
elif street == 'otto-c-huismanstraat':
street = 'o-c-huismanstraat'
elif street == 'hammarskjoldhof':
street = 'hammarskjoeldhof'
elif street == 'doctor-huber-noodtstraat':
street = 'dr-huber-noodtstraat'
elif street == 'monseigneur-borretweg':
street = 'mgr-borretweg'
elif street == 'sint-wirosingel':
street = 'st-wirosingel'
elif street == 'e-d-s-plein':
# Ed heeft een eigen plein:
street = 'eds-plein'
Merk op dat zowel de BAG als Lidl soms raar omgaan met namen.
Nu ik alle filiaalpagina’s had, ben ik even gaan kijken of daar nog iets nuttigs mee gedaan kon worden. Daarbij is deze nota van de Licensing Working Group relevant. Het is ons toegestaan om van primaire bronnen zoals de website van een winkel zelf feiten zoals de openingstijden over te nemen.
Ik noem hier voor de volledigheid ook even All The Places, dat is een project waar met scripts zoals deze dit soort data verzameld wordt. Er wordt ook gekeken of wij in OpenStreetMap met deze All The Places data kunnen werken, maar daar zitten nog wel wat haken en ogen aan (zie mijn opmerking over de Nederlandse Lidl’s daar ook). Voorlopig nog niet.
Ik heb het scriptje uitgebreid met een eenvoudig stukje openingstijden uitlezen. Dit staat op de Lidl-pagina’s redelijk gestructureerd:
<div class="lirt-o-store-detail-card__times-container">
<h2 class="lirt-o-store-detail-card__openingHours-headline">Openingstijden</h2>
<div class="lirt-o-store-detail-card__openingHours-data lirt-o-store-detail-card__openingHours-data--first-line-bolded">
<p>Vr 08:00-21:00 </p>
<p>Za 08:00-21:00 </p>
<p>Zo 09:00-18:00 </p>
<p>Ma 08:00-21:00 </p>
<p>Di 08:00-21:00 </p>
<p>Wo 08:00-21:00 </p>
<p>Do 08:00-21:00 </p>
</div>
</div>
Perfect is het niet. Het viel me namelijk bij Kruidvat al op dat ook met gestructureerde schema’s kan die bedoeld zijn om uit te lezen met een script:
<!-- Store MicroData -->
<div itemscope itemtype="http://schema.org/LocalBusiness" style="display:none">
<span itemprop="url">/store/drogisterij-kruidvat-6572</span>
<span itemprop="name">DROGISTERIJ KRUIDVAT 6572</span>
<span itemprop="description">store.details.schema.markup.description</span>
<div itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
<span itemprop="streetAddress">Dapperplein 62</span>
<span itemprop="addressLocality">Amsterdam</span>
<span itemprop="addressRegion"></span>
<span itemprop="postalCode">1093GS</span>
<span itemprop="addressCountry">Nederland</span>
</div>
<span itemprop="openingHours" content="Mon 9:00-18:00">Maandag<nbsp/>
9:00 - 18:00</span>
<span itemprop="openingHours" content="Tue 9:00-18:00">Dinsdag<nbsp/>
9:00 - 18:00</span>
<span itemprop="openingHours" content="Wed 9:00-18:00">Woensdag<nbsp/>
9:00 - 18:00</span>
<span itemprop="openingHours" content="Thu 9:00-18:00">Donderdag<nbsp/>
9:00 - 18:00</span>
<span itemprop="openingHours" content="Fri 9:00-18:00">Vrijdag<nbsp/>
9:00 - 18:00</span>
<span itemprop="openingHours" content="Sat 9:00-18:00">Zaterdag<nbsp/>
9:00 - 18:00</span>
<span itemprop="openingHours" content="Sun 12:00-17:00">Zondag<nbsp/>
12:00 - 17:00</span>
</div>
<!-- End Store MicroData -->
Je zou het beheer van de Kruidvat-filialen op OpenStreetMap dus bijna geheel door een script kunnen laten doen. Voordelig!
Die ambitie heb ik verder niet met dit script. Wat ik wel wil doen is hem uitvoeren en de data uploaden. Dit zijn trouwens alle openingstijden die hij kon vinden (dubbelingen verwijderd, gesorteerd). Steeksproefgewijs zie ik nog geen fouten.
Wat het script doet:
website
toevoegen na testen ervan.opening_hours
updaten.- Deze tags gelijk trekken:
brand:website=https://www.lidl.nl/
brand:wikipedia=nl:Lidl
brand:wikidata=Q151954
operator=Lidl Nederland GmbH
De invoer van het script is de uitvoer van deze Overpass-query.
Dit is het soort script dat je eens in de zoveel tijd kan uitvoeren, maar er is geen garantie dat het een volgende keer precies zo werkt als Lidl de website aanpast. Maar ook als het bij deze ene keer blijft is het volgens mij een waardevolle update van meer dan 400 winkels.
Dit is de uitvoer van het script (open maar eens in JOSM!)
Zien jullie nog fouten of rare dingen?