-
Notifications
You must be signed in to change notification settings - Fork 2
/
eol_api_wrapper.py
308 lines (240 loc) · 11.8 KB
/
eol_api_wrapper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
from urllib.request import urlopen
import json
import math
class API(object):
'''Methods for accessing the API'''
def __init__(self,key=''):
self.key = key
'''Api instance constructor
Parameters
---------
key: Optional argument which adds your API key to all API calls made from this object '''
@staticmethod
def _get_url(url):
'''Get json page data using a specified eol API url'''
response = urlopen(url)
data = str(response.read().decode('utf-8'))
page = json.loads(data)
return page
@staticmethod
def _bool_converter(string):
'''Convert Python bools to the correct format'''
_bool_dict = {True: 'true', False:'false'}
return _bool_dict[string]
@staticmethod
def ping():
'''Check whether the API is working'''
url = "http://eol.org/api/ping/1.0.json"
ping = API._get_url(url)
return ping['response']['message']
def Page(self, id, images = 2, videos = 0, sounds = 0, \
maps = 0, text = 2, iucn = False, subjects = 'overview', \
licences = 'all', details = True, common_names = True, \
synonyms = True, references = True, vetted = 0):
'''
Takes an EOL page identifier and returns the scientific name for that page, and optionally
returns information about common names, media (text, images and videos), and references to the
hierarchies which recognize the taxon described on the page.
Parameters
---------
Parameters can be found here: http://eol.org/api/docs/pages
id is the only required argument; the rest are optional
Booleans are entered in Pythonic form (e.g. False, rather than 'false')
Example
------
>>> api = API()
>>> page = api.Page(1045608)
>>> page.scientific_name
'Apis mellifera Linnaeus 1758'
'''
return Page(id, images, videos, sounds, maps, text, iucn, subjects, licences, details, common_names, synonyms, references, vetted, self.key)
def Search(self, q, page = 1, exact = False, filter_by_taxon_concept_id = '', filter_by_hierarchy_entry_id = '',\
filter_by_string = '', cache_ttl = ''):
'''
Search the EOL API with a string.
Parameters
---------
Parameters can be found here: http://eol.org/api/docs/search
The search string is the only required argument; the rest are optional.
An optional page='all' argument has been added to allow you to retrieve all
of the appended results pages for a given search.
Booleans are entered in Pythonic form (e.g. False, rather than 'false').
Example
------
>>> api = API()
>>> search = api.Search('Ursus')
Retrieving page 1
>>> search.q
'Ursus'
'''
return Search(q, page, exact, filter_by_taxon_concept_id, filter_by_hierarchy_entry_id ,filter_by_string, cache_ttl, self.key)
def Collection(self, id, page = 1, per_page = 50, filter = 'none', sort_by='recently_added', sort_field='', cache_ttl=''):
'''
Given the identifier for a collection this API will return all metadata about the collection and the items it contains.
Parameters
---------
Parameters can be found here: http://eol.org/api/docs/collections
The collection id is the only required argument; the rest are optional
Booleans are entered in Pythonic form (e.g. False, rather than 'false')
Example
------
>>> api = API()
>>> collection = api.Collection(176)
>>> collection.name
'EOL Group on Flickr'
'''
return Collection(id,page,per_page,filter, sort_by, sort_field, cache_ttl, self.key)
def DataObject(self, id, cache_ttl = ''):
'''
Given the identifier for a data object this API will return all metadata about the object as
submitted to EOL by the contributing content partner.
Parameters
---------
Parameters can be found here: http://eol.org/api/docs/data_objects
The id is the only required argument; cache ttl is optional
Example
------
>>> api = API()
>>> dataobject = api.DataObject(30073527)
>>> dataobject.scientific_name
'Apis mellifera Linnaeus 1758'
'''
return DataObject(id, cache_ttl, self.key)
def Hierachy_entries(self,id, common_names = False, synonyms = False, cache_ttl=''):
'''
The Encyclopedia of Life does not have a singular taxonomic hierarchy upon which it creates its pages.
Rather EOL indexes many hierarchies and compares them against each other.
As a result any EOL page may relate to several nodes from various hierarchies.
This API gives access to a single hierarchy and its internal relationships.
Parameters
---------
Parameters can be found here: http://eol.org/api/docs/hierarchy_entries
The id is the only required argument; the rest are optional
Booleans are entered in Pythonic form (e.g. False, rather than 'false')
Example
------
>>> api = API()
>>> hierachy = api.Hierachy_entries(63220654)
>>> hierachy.scientific_name
'Dubosquellidae'
'''
return Hierachy_entries(id, common_names, synonyms, cache_ttl, self.key)
def __repr__(self):
return '<%s (key = %s)>' % (
self.__class__.__name__, self.key
)
class Page(object):
'''
Takes an EOL identifier and returns a dictionary of information about that page.
Use kwargs to set other attributes
'''
def __init__(self, id, images = 2, videos = 0, sounds = 0, \
maps = 0, text = 2, iucn = False, subjects = 'overview', \
licences = 'all', details = True, common_names = True, \
synonyms = True, references = True, vetted = 0, key=''):
attributes = [id, images, videos, sounds, maps, text, API._bool_converter(iucn),\
subjects, licences, API._bool_converter(details), API._bool_converter(common_names), API._bool_converter(synonyms),\
API._bool_converter(references), vetted, key]
self.id = id
self.key = key
url = (
"http://eol.org/api/pages/1.0/{0}.json?images={1}&videos={2}&sounds={3}"
"&maps={4}&text={5}&iucn={6}&subjects={7}&licenses={8}&details={9}&common_names={10}"
"&synonyms={11}&references={12}&vetted={13}&cache_ttl=&key={14}".format(*attributes)
)
page = API._get_url(url)
self.scientific_name = page["scientificName"]
self.richness_score = page["richness_score"]
self.synonyms = page["synonyms"]
self.common_names = page["vernacularNames"]
self.references = page["references"]
self.taxon_concepts = page["taxonConcepts"]
self.data_objects = page["dataObjects"]
class Search(object):
'''Searches the EOL database with the string you supply'''
def __init__(self, q, page = 1, exact = False, filter_by_taxon_concept_id = '', filter_by_hierarchy_entry_id = '',
filter_by_string = '', cache_ttl = '', key=''):
if not isinstance(page, int) and page!='all':
raise ValueError('Not a valid page number')
attributes = [q,page,API._bool_converter(exact),filter_by_taxon_concept_id, filter_by_hierarchy_entry_id, filter_by_string, cache_ttl, key]
url = (
"http://eol.org/api/search/1.0.json?q={0}&page={1}&exact={2}&filter_by_taxon_concept_id={3}"
"&filter_by_hierarchy_entry_id={4}&filter_by_string={5}&cache_ttl={6}&key={7}".format(*attributes))
search = API._get_url(url)
self.q = q
self.total_results = search["totalResults"]
self.startIndex = search["startIndex"]
self.items_per_page = search["itemsPerPage"]
if page == 'all':
self.key = key
self.results = []
self.total_pages = math.ceil(self.total_results/30)
for page in range(1,self.total_pages+1):
print("Retrieving page {} of {}".format(page,self.total_pages))
attributes = [q,page,API._bool_converter(exact),filter_by_taxon_concept_id, filter_by_hierarchy_entry_id, filter_by_string,cache_ttl,key ]
url = (
"http://eol.org/api/search/1.0.json?q={0}&page={1}&exact={2}&filter_by_taxon_concept_id={3}"
"&filter_by_hierarchy_entry_id={4}&filter_by_string={5}&cache_ttl={6}&key={7}".format(*attributes))
search = API._get_url(url)
self.results+=search["results"]
self.first = search["first"]
self.last = search["last"]
else:
print("Retrieving page {}".format(page))
self.key = key
self.results = search["results"]
self.first = search["first"]
self.self = search["self"]
self.last = search["last"]
try:
self.next = search["next"]
except KeyError:
pass
class Collection(object):
'''Returns all metadata about the collection and the items it contains'''
def __init__(self, id, page = 1, per_page = 50, filter = 'none', sort_by='recently_added', sort_field='', cache_ttl='', key = ''):
attributes = [id,page,per_page,filter, sort_by, sort_field, cache_ttl, key]
self.key = key
url = ("http://eol.org/api/collections/1.0/{}.json?page={}&per_page={}&filter={}&sort_by={}&sort_field={}&cache_ttl={}&key={}".format(*attributes))
collection = API._get_url(url)
self.name = collection["name"]
self.description = collection["description"]
self.created = collection["created"]
self.modified = collection["modified"]
self.total_items = collection["total_items"]
self.item_types = collection["item_types"]
self.collection_items = collection["collection_items"]
class DataObject(object):
'''Given the identifier for a data object this API will return all metadata about the object as submitted to EOL by the contributing content partner'''
def __init__(self, id, cache_ttl = '', key = ''):
attributes = [id, cache_ttl, key]
self.key = key
url = "http://eol.org/api/data_objects/1.0/{}.json?cache_ttl={}&key={}".format(*attributes)
data_object = API._get_url(url)
self.identifier = id
self.scientific_name = data_object["scientificName"]
self.exemplar = data_object["exemplar"]
self.richness_score = data_object["richness_score"]
self.synonyms = data_object["synonyms"]
self.data_objects = data_object["dataObjects"]
self.references = data_object["references"]
class Hierachy_entries(object):
def __init__(self,id, common_names = False, synonyms = False, cache_ttl='', key = ''):
attributes = [id, API._bool_converter(common_names), API._bool_converter(synonyms), cache_ttl, key]
url = "http://eol.org/api/hierarchy_entries/1.0/{}.json?common_names={}&synonyms={}&cache_ttl={}&key={}".format(*attributes)
hierachy = API._get_url(url)
self.key = key
self.id = id
self.source_identifier = hierachy["sourceIdentifier"]
self.taxon_id = hierachy["taxonID"]
self.parent_name_usage_id = hierachy["parentNameUsageID"]
self.taxon_concept_id = hierachy["taxonConceptID"]
self.scientific_name = hierachy["scientificName"]
self.taxon_rank = hierachy["taxonRank"]
self.source = hierachy["source"]
self.name_according_to = hierachy["nameAccordingTo"]
self.vernacularNames = hierachy["vernacularNames"]
if __name__ == '__main__':
#run doctests
import doctest
doctest.testmod()