@@ -0,0 +1,193 @@
1+import json
2+from datetime import datetime
3+from requests import get
4+from urllib import urlencode
5+
6+resultCount=2
7+urlSearch = 'https://www.wikidata.org/w/api.php?action=query&list=search&format=json&srnamespace=0&srprop=sectionsnippet&{query}'
8+urlDetail = 'https://www.wikidata.org/w/api.php?action=wbgetentities&format=json&props=labels%7Cinfo%7Csitelinks%7Csitelinks%2Furls%7Cdescriptions%7Cclaims&{query}'
9+# find the right URL for urlMap
10+urlMap = 'http://www.openstreetmap.org/?lat={latitude}&lon={longitude}&zoom={zoom}&layers=M'
11+
12+def request(query, params):
13+ params['url'] = urlSearch.format(query=urlencode({'srsearch': query, 'srlimit': resultCount}))
14+ print params['url']
15+ return params
16+
17+
18+def response(resp):
19+ results = []
20+ search_res = json.loads(resp.text)
21+ # TODO parallel http queries
22+ before = datetime.now()
23+ for r in search_res.get('query', {}).get('search', {}):
24+ wikidata_id = r.get('title', '')
25+ results = results + getDetail(wikidata_id)
26+ after = datetime.now()
27+ print str(after - before) + " second(s)"
28+
29+ return results
30+
31+def getDetail(wikidata_id):
32+ language = 'fr'
33+
34+ url = urlDetail.format(query=urlencode({'ids': wikidata_id, 'languages': language + '|en'}))
35+ print url
36+ response = get(url)
37+ result = json.loads(response.content)
38+ result = result.get('entities', {}).get(wikidata_id, {})
39+
40+ title = result.get('labels', {}).get(language, {}).get('value', None)
41+ if title == None:
42+ title = result.get('labels', {}).get('en', {}).get('value', wikidata_id)
43+ results = []
44+ urls = []
45+ attributes = []
46+
47+ description = result.get('descriptions', {}).get(language, {}).get('value', '')
48+ if description == '':
49+ description = result.get('descriptions', {}).get('en', {}).get('value', '')
50+
51+ claims = result.get('claims', {})
52+ official_website = get_string(claims, 'P856', None)
53+ print official_website
54+ if official_website != None:
55+ urls.append({ 'title' : 'Official site', 'url': official_website })
56+ results.append({ 'title': title, 'url' : official_website })
57+
58+ if language != 'en':
59+ add_url(urls, 'Wikipedia (' + language + ')', get_wikilink(result, language + 'wiki'))
60+ wikipedia_en_link = get_wikilink(result, 'enwiki')
61+ add_url(urls, 'Wikipedia (en)', wikipedia_en_link)
62+
63+ if language != 'en':
64+ add_url(urls, 'Wiki voyage (' + language + ')', get_wikilink(result, language + 'wikivoyage'))
65+ add_url(urls, 'Wiki voyage (en)', get_wikilink(result, 'enwikivoyage'))
66+
67+ if language != 'en':
68+ add_url(urls, 'Wikiquote (' + language + ')', get_wikilink(result, language + 'wikiquote'))
69+ add_url(urls, 'Wikiquote (en)', get_wikilink(result, 'enwikiquote'))
70+
71+
72+ add_url(urls, 'Commons wiki', get_wikilink(result, 'commonswiki'))
73+
74+ add_url(urls, 'Location', get_geolink(claims, 'P625', None))
75+
76+ add_url(urls, 'Wikidata', 'https://www.wikidata.org/wiki/' + wikidata_id + '?uselang='+ language)
77+
78+ postal_code = get_string(claims, 'P281', None)
79+ if postal_code != None:
80+ attributes.append({'label' : 'Postal code(s)', 'value' : postal_code})
81+
82+ date_of_birth = get_time(claims, 'P569', None)
83+ if date_of_birth != None:
84+ attributes.append({'label' : 'Date of birth', 'value' : date_of_birth})
85+
86+ date_of_death = get_time(claims, 'P570', None)
87+ if date_of_death != None:
88+ attributes.append({'label' : 'Date of death', 'value' : date_of_death})
89+
90+
91+ results.append({
92+ 'infobox' : title,
93+ 'id' : wikipedia_en_link,
94+ 'content' : description,
95+ 'attributes' : attributes,
96+ 'urls' : urls
97+ })
98+
99+ return results
100+
101+def add_url(urls, title, url):
102+ if url != None:
103+ urls.append({'title' : title, 'url' : url})
104+
105+def get_mainsnak(claims, propertyName):
106+ propValue = claims.get(propertyName, {})
107+ if len(propValue) == 0:
108+ return None
109+
110+ propValue = propValue[0].get('mainsnak', None)
111+ return propValue
112+
113+def get_string(claims, propertyName, defaultValue=None):
114+ propValue = claims.get(propertyName, {})
115+ if len(propValue) == 0:
116+ return defaultValue
117+
118+ result = []
119+ for e in propValue:
120+ mainsnak = e.get('mainsnak', {})
121+
122+ datatype = mainsnak.get('datatype', '')
123+ datavalue = mainsnak.get('datavalue', {})
124+ if datavalue != None:
125+ result.append(datavalue.get('value', ''))
126+
127+ if len(result) == 0:
128+ return defaultValue
129+ else:
130+ return ', '.join(result)
131+
132+def get_time(claims, propertyName, defaultValue=None):
133+ propValue = claims.get(propertyName, {})
134+ if len(propValue) == 0:
135+ return defaultValue
136+
137+ result = []
138+ for e in propValue:
139+ mainsnak = e.get('mainsnak', {})
140+
141+ datatype = mainsnak.get('datatype', '')
142+ datavalue = mainsnak.get('datavalue', {})
143+ if datavalue != None:
144+ value = datavalue.get('value', '')
145+ result.append(value.get('time', ''))
146+
147+ if len(result) == 0:
148+ return defaultValue
149+ else:
150+ return ', '.join(result)
151+
152+def get_geolink(claims, propertyName, defaultValue=''):
153+ mainsnak = get_mainsnak(claims, propertyName)
154+
155+ if mainsnak == None:
156+ return defaultValue
157+
158+ datatype = mainsnak.get('datatype', '')
159+ datavalue = mainsnak.get('datavalue', {})
160+
161+ if datatype != 'globe-coordinate':
162+ return defaultValue
163+
164+ value = datavalue.get('value', {})
165+
166+ precision = value.get('precision', 0.0002)
167+
168+ # there is no zoom information, deduce from precision (error prone)
169+ # samples :
170+ # 13 --> 5
171+ # 1 --> 6
172+ # 0.016666666666667 --> 9
173+ # 0.00027777777777778 --> 19
174+ # wolframalpha : quadratic fit { {13, 5}, {1, 6}, {0.0166666, 9}, {0.0002777777,19}}
175+ # 14.1186-8.8322 x+0.625447 x^2
176+ if precision < 0.0003:
177+ zoom = 19
178+ else:
179+ zoom = int(15 - precision*8.8322 + precision*precision*0.625447)
180+
181+ url = urlMap.replace('{latitude}', str(value.get('latitude',0))).replace('{longitude}', str(value.get('longitude',0))).replace('{zoom}', str(zoom))
182+
183+ return url
184+
185+def get_wikilink(result, wikiid):
186+ url = result.get('sitelinks', {}).get(wikiid, {}).get('url', None)
187+ if url == None:
188+ return url
189+ elif url.startswith('http://'):
190+ url = url.replace('http://', 'https://')
191+ elif url.startswith('//'):
192+ url = 'https:' + url
193+ return url