今天也是找到了一個蠻有趣的 API ,叫做 GDELT Geo API。 GDELT 的全名是 Global Database of Events, Language, and Tone (全球事件、語言、音調資料庫),Google 中文的資料,也有翻譯成全球社會資料庫跟世界整合新聞數據庫的。GDELT 專案裡存放了從 1979 年到現在、全世界超過一百種語言的廣播、電視、網路新聞、紙本媒體的資料,是個即時、開放的全球地圖資料集。
在他們的網站上這樣寫著:
“The GDELT Project is an initiative to construct a catalog of human societal-scale behavior and beliefs across all countries of the world, connecting every person, organization, location, count, theme, news source, and event across the planet into a single massive network that captures what's happening around the world, what its context is and who's involved, and how the world is feeling about it, every single day."
GDELT Project 是一項倡議,旨在建立一個跨世界所有國家的人類社會規模的行為和信仰目錄,將全球每個人,組織,地點,數量,主題,新聞來源和事件連接在一起,成為一個大規模網絡,它每天捕捉世界各地正在發生的事情,事件的發生背景及參與者,以及世界的反應,每天。(翻譯 by Google)
聽起來好像很厲害。直接把文件翻開來看看有什麼可以利用的東西吧。
雖然有個看似威猛強大的精神跟目標,但他們的 API 寫在一個沒有 Navigation Bar 的單張 HTML 的 Blog Post 裡面。甚至還不太好找,藏在眾多的部落格文裡,跟舊版本的文件混在一起。
這邊要注意的地方是,GDELT 有好幾個 API。
而他們個別的文件都寫在部落格裡沒有一個目錄把他們全部列出來,我一直以為 DOC API 是指 API 的文件,但他其實是其中一個 API 。
DOC API 裡回傳的是各種事件跟圖片的資料, Geo API 裡回傳的是地圖資料,可以選擇 GeoJSON 的格式。
我們今天要使用的是 GeoJSON。
在 Quick Example 那邊,有許多範例可以點。以第一個來說是
Point-level map of all locations mentioned near "trump".
- URL: https://api.gdeltproject.org/api/v2/geo/geo?query=trump
在地圖上找到提到川普的點。直接看他的 URL 可以知道,
這個 API Request URL 的 endpoint 是 [https://api.gdeltproject.org/api/v2/geo/geo](https://api.gdeltproject.org/api/v2/geo/geo?query=trump)
。
而必要的參數是 query
。
把這連結打開,會看到一張地圖。
滑鼠放到那些點上面的時候,會出現一個小框框,裡面寫著地點跟在此地點提到川普的數量跟相關連結。
由於今天時間比較有限,不一一講解其他參數,我只挑幾個我用的講:
format
:基本上有 HTML 跟 GeoJSON 兩種,有 Image 前綴的表示只顯示含有圖片的資料HTML
、ImageHTML
、ImageHTMLShow
、GeoJSON
、ImageGeoJSON
timespan
:搜尋一段時間內的結果,預設是 24 小時,間隔最短可以到 15 分鐘
maxpoints
:在 Point-Mode 地圖的情況下,限制最多顯示的點。在不同類型的點地圖上限制不一樣
Pointdata Mode 1-1000 地點
PointHeatmap Mode 1-25000 地點
PointAnimation Mode 1-10000 地點
現在我們就把 format 改成 GeoJSON 然後寫個基本 request 。
在這邊我想找的是全世界 24 小時內提及 “Javascript“ 的人、新聞、事件的地點。
var query= "javascript";
var url = "https://api.gdeltproject.org/api/v2/geo/geo?query="
+ query
+"&format=GeoJSON";
function makeRequest() {
xhr = new XMLHttpRequest();
xhr.onload = function() {
var response = JSON.parse(this.responseText);
data = response;
console.log(data)
window.eqfeed_callback(data);
};
xhr.open("GET",url,true);
xhr.send();
}
makeRequest();
還蠻順利的就拿到 response,畢竟不用 API Key 什麼的。如果拿不到正確 response的話,很可能是 format 沒設定好以致於顯示不出資料。
那現在我們有了一個 GeoJSON,把這些資料畫到地圖上吧。
我還沒有使用過 Google Map,今天就來使用一下。
畢竟是Google Map 呀,大家應該都很熟悉,我就不需要寫拿到 API Key 的過程了。
Google Map Javascript API 是一個可以讓你使用一些簡單指令展示 Google Map 跟修改的 API。
今天我使用的範例是這個:Visualising Data
如他教學範例寫的,跟著複製貼上一下:
先在 HTML 的 Body 底部放上 <script>
:
<body>
<div id="map"></div>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>
</body>
在 JS 檔案裡面:
var query= "javascript";
var url = "https://api.gdeltproject.org/api/v2/geo/geo?query="
+ query
+"&format=GeoJSON";
var data=[];
function makeRequest() {
xhr = new XMLHttpRequest();
xhr.onload = function() {
var response = JSON.parse(this.responseText);
data = response;
// loop 出地點的 function
window.feed_callback(data);
};
xhr.open( "GET",url,true);
xhr.send();
}
makeRequest();
//設定地圖
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 2,
center: new google.maps.LatLng(2.8,-187.3),
mapTypeId: 'terrain'
});
}
window.feed_callback = function(data) {
for (var i = 0; i < data.features.length; i++) {
var coords = data.features[i].geometry.coordinates;
var latLng = new google.maps.LatLng(coords[1],coords[0]);
var marker = new google.maps.Marker({
position: latLng,
map: map,
label:data.features[i].properties.count.toString()
});
}
}
在 Google 範例裡面的 Code,關於地震的 GeoJSON 是另外放進去的,但我們已經有一個 GeoJSON 了呀。
為了讓我們拿回來的 response 可以被其他 function 使用,我宣告了一個 data
變數,然後在 xhr.onload()
裡面把 response
放進 data
裡面。
然後範例裡幫我寫好,把 GeoJSON loop 出來的這個 callback,我把它放進 onload
裡然後傳入 data
參數。由於 GeoJSON 上面的格式是統一的,我拿到的 GeoJSON 直接丟進這個 window.feed_callback
裡就直接可以用了。
最後,我想在地圖上加上各點的提到JS 的數量,於是在 marker 的設定裡加上了 label
:
marker = new google.maps.Marker({
position: latLng,
map: map,
label: data.features[i].properties.count.toString()
});
由於 count
是個數字,但label 一定要放 string
,所以在後面接了個 toString()
。
今天先告一個段落。