CoolFace
Apppublic

wfr2/species-synonym-api

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
fuzzy_search.py63 linesDownload Raw Back to utils
1"""2fuzzy_search.py3 4Fuzzy species name lookup against the GBIF Backbone Taxonomy.5 6    from scripts.utils.fuzzy_search import fuzzy_search7 8    fuzzy_search("Amanita muscaria")  # exact match  -> ["Amanita muscaria"]9    fuzzy_search("Amanita muscara")   # no exact match -> ['Amanita muscaria', 'Amanitaria muscaria']10"""11 12import requests13 14GBIF_BASE = "https://api.gbif.org/v1"15 16 17def fuzzy_search(query):18    """19    Search the GBIF Backbone Taxonomy for a species name.20 21    Always returns a list. Returns a single-item list for exact species matches,22    or a deduplicated list of suggestions from /species/suggest otherwise.23    """24    # strict=false allows fuzzy matching, not just exact.25    match_resp = requests.get(26        f"{GBIF_BASE}/species/match",27        params={"name": query, "strict": "false"},28        timeout=30,29    )30    match_resp.raise_for_status()31    match = match_resp.json()32 33    match_type = match.get("matchType")34 35    # Case: EXACT at species rank or FUZZY — return single-item list with the resolved name.36    if (37        match_type == "EXACT" and match.get("rank") == "SPECIES"38    ) or match_type == "FUZZY":39        return [match.get("canonicalName")]40 41    suggest_query = query42 43    # All other cases (HIGHERRANK, NONE, or EXACT above species rank) fall through to /species/suggest.44    # /species/suggest is an independent prefix search and can surface candidates even when the backbone match fails entirely.45    suggest_resp = requests.get(46        f"{GBIF_BASE}/species/suggest",47        params={"q": suggest_query, "limit": 10, "rank": "SPECIES"},48        timeout=30,49    )50    suggest_resp.raise_for_status()51 52    # Build a deduplicated list of candidate names.53    # The suggest endpoint can return the same species under multiple checklists.54    seen = set()55    suggestions = []56    for s in suggest_resp.json():57        name = s.get("canonicalName", "")58        if name and name not in seen:59            seen.add(name)60            suggestions.append(name)61 62    return suggestions63