How do I get from an animal name (tiger
) to its WikiData entity id (Q19939
) in a static website?
I am writing a small static website (no backend, just html and vanilla javascript) where the user enters the name of an animal (tiger
) and the website displays information about that animal.
I want to get the shown data from WikiData. (I am new to WikiData, so this is a good opportunity to learn). This works great if I have the WikiData entity id (Q19939 for tiger). With that I can query the wikidata-sparql-api and get all the data I need.
How do I get the WikiData entity id (Q19939
) from the animal name (tiger
)?
Here is a minimal example of how the final website might look like:
<!doctype html>
<html>
<body>
<div id="output"></div>
<script>
async function getWikidataId(entityName) {
// TODO find id somehow
return undefined;
}
async function tell_reader_about(animalName) {
const wikidataId = await getWikidataId(animalName);
document.getElementById("output").innerText =
`${animalName} has WikiData entity ID ${wikidataId}`;
}
tell_reader_about("tiger");
</script>
</body>
</html>
I see mainly two ways here:
The MediaWiki API seems perfect for my usecase. I can provide the animal name as an query parameter.
https://www.wikidata.org/w/api.php?action=wbsearchentities&search=tiger&language=en
It returns a list of fitting wikidata entities with a description.
{
"search": [
{
"id": "Q79081545",
"label": "Tiger",
"description": "unisex given name",
...
},
{
"id": "Q19939",
"label": "tiger",
"description": "species of big cat",
...
},
{
"id": "Q16282104",
"label": "Tiger",
"description": "family name",
},
...
],
"search-continue": 7,
"success": 1,
...
}
This is awesome, from here I could choose which id is the right one and use it.
But when I do this in my static website I get the following error:
Cross-Origin Request Blocked:
The Same Origin Policy disallows reading the remote resource at https://www.wikidata.org/w/api.php?action=wbsearchentities&search=apple&language=de&format=json.
(Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
Status code: 200.
This sounds to me like that API is not available for me to use. Or is there a way to make this work?
I could try to do another sparql request. (The sparql API seemingly has that CORS header set) As far as I can see Wikidata doesn't like to match entities against strings, only against other entities. But it should work in theory. I tried a few queries, but they all timed out or didn't give me any results.
SELECT ?item ?itemLabel WHERE {
?item wdt:P31 wd:Q16521.
FILTER(LCASE(?itemLabel) = LCASE("tiger")) .
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],mul,en". }
}
I can think of multiple solutions to this problem:
As @UninformedUser said: Use entity search via SPARQL:
SELECT ?item
WHERE {
SERVICE wikibase:mwapi {
bd:serviceParam wikibase:api "EntitySearch" ;
wikibase:endpoint "www.wikidata.org" ;
mwapi:search "tiger" ;
mwapi:language "en" .
?item wikibase:apiOutputItem mwapi:item .
?num wikibase:apiOrdinal "true"^^xsd:boolean .
}
}
ORDER BY (?num)
LIMIT 5