Wikidata與OSM的串聯及補齊

Ting Chia

2020-12-22

身為測量與空間資訊系的學生,在過去課程中接觸了很多有關地理資訊系統方面的東西,因此深深的感受到在台灣,開放的資料庫似乎仍不是這樣的普及,許多資料幾乎都是由政府的資料庫取得,因此非常仰賴資料的開放度。暑假於莊庭瑞老師的實驗室中,接觸了開放資料與開源,使用了以群眾力量建構的資料庫Wikidata與開放地圖OpenStreetMap。

初衷與目的

Wikidata與OpenStreetMap皆是常用的開放資料庫,利用群眾力量擴充資料庫。然而在Wikidata中,雖有許多知名建物、地理位置等,但是這些地點在Wikidata中皆只以一個點作為代表,以地理資訊系統的觀點而言,是非常不足的。而在OpenStreetMap中,雖有足夠的點線面等地理圖層,然而圖層中的屬性資料相較Wikidata仍非常不足。 而在Wikidata與OpenStreetMap中資料皆不齊全的原因有二,一為編寫兩者的人不同,因此進度也有所不同,如OSM可能注重於地理特徵(點,線,面,關聯),而Wikidata注重資料來源與資料間連接;二為Wikidata的地理表現不夠,只有用node的座標展現,且node之間無法疊圖(不能呈現關係)、OpenStreetMap則是Attribute Table較簡陋,且只有地理座標上的連接,因此想到若將兩者進行串聯,甚至在串聯後進行資料庫的補齊,對於開放資料庫皆為很大的貢獻。

對於Wikidata與OpenStreetMap的了解與前置作業

在進行串聯前,我們需要先對於Wikidata與OpenStreetMap有幾個認識:

  1. 資料庫中,資料的識別碼可謂資料的身分證字號,在Wikidata中稱為Qid,而在OpenStreetMap中則稱為(Node/Polyline/Polygon/Relation) id。
  2. 連接方式:Wikidata是以OSM Relation id(OSM關聯碼)對OpenStreetMap進行連接,而OpenStreetMap則是以在Attribute Table中新增一tags稱為wikidata,為Qid為連接方式
  3. Wikidata中資料庫建立較為嚴格,而在OpenStreetMap中建立一新資料較容易,因此在OpenStreetMap中有許多資料為使用者個人使用,非提供與大眾使用。
  4. 以資料的批次上傳而言,Wikidata有可以直接使用的Quickstatements來上傳資料,並且只要將想增加的欄位複製貼上即可,非榮直觀、容易;然而在OpenStreetMap中,需要以原始的完整資料進行修改,並且轉換為更正檔,才能進行批次上傳,類似於git中,需要上傳資料前,需要先將資料pull out,將所要增加或刪減的資料修正後,才能夠push回去,是類似的原理,因此愛批次上傳下資料修正後,才能夠push回去,是類似的原理,因此在OpenStreetMap的批次上傳是較為複雜、多程序的。

步驟

  1. 同時在Wikidata與OpenStreetMap中進行資料的採集
  2. Wikidata:使用Wikidata Query進行資料的收集 (然而若收集全台灣的所有資料會太過龐大,因此以下為全台灣之學校作為串聯對象) SPARQL= SELECT ?item ?itemLabel ?itemDescription (GROUP_CONCAT(DISTINCT(?altLabel); separator = ", ") AS ?altLabel_list) WHERE { ?item wdt:P31/wdt:P279* wd:Q3914; wdt:P17 wd:Q865. OPTIONAL { ?item skos:altLabel ?altLabel . FILTER (lang(?altLabel) in ("zh","zh-tw","en","zh-hant")) } SERVICE wikibase:label { bd:serviceParam wikibase:language "zh","zh-tw","en","zh-hant". } } GROUP BY ?item ?itemLabel ?itemDescription
  3. OpenStreetMap:使用Overpass Turbo搜尋所有的Relation搜尋所有的Relation [out:csv( ::"id",name,wikidata; true; "," )]; relation ({{bbox:22,120,25,122}}); /*added by auto repair*/ (._;>;); /*end of auto repair*/ out;
  4. 兩邊資料進行比對,以name,alias進行純文字資料集每個欄位一一的比對,對應即補上其串聯碼,並匯出新表格資料。若已有串聯,則不進行輸出。
  5. 以csv對照(以label名稱對應alias/label來找到對應Oid)為例
    • 以A資料有label無Qid(來自OSM Query)
    • B資料有label,alias,Qid(來自Wikidata Query)
      IFNA(INDEX(B-Qid,match(A-label,B-label或B-alias,0)),0)
有對應則回傳Qid,沒有則回傳0
  1. 將Wikidata與OpenStreetMap進行回傳Upload
  2. Wikidata
    • Wikidata加上Pid(Pid為Value的屬性,因此此資料集中Pid為OSM識別碼)
    • Quickstatements進行上傳
  3. OpenStreetMap
    • 使用JOSM將原始OSM檔(.osm)下載後,會得到一xml格式之檔案
    • 將要增加的wikidata Qid加入
    • 使用osm2change.py將osm轉換為osc,在OpenStreetMap中,osm與osc皆為xml的資料格式,不同在於osm為資料庫中處存之資料格式,而osc則為告訴資料庫要增加、刪改、更正等資料庫變化檔案 ./osm2change.py file.osm
    • 利用upload.py將資料進行上傳 ./upload.py -u username -p password -c yes -m 'add wikidata' file.osc

Wikidata與OSM的自動化串聯

此次研究中,因為步驟十分繁瑣,因此我自行寫了數個程式,配合原有的upload.py,將整個串連動作進行自動化的串聯,讓非Wikidata專業與OpenStreetMap的使用者皆可以進行資料串連,並且可以針對不同地區、不同對象進行串聯。 以下程式皆可於此下載:自動化串聯

  1. 雙邊進行爬蟲,將原始資料下載
  2. OpenStreetMap:queryOSM.py
  3. Wikidata:querywiki.py 皆是以selenium的webdriver模擬滑鼠及虛擬鍵盤,進行模擬滑鼠及虛擬鍵盤,進行資料的收集下載。
  4. 資料比對:comparecsv.py 將xml轉為動態陣列後,使其重複比對,直到比對成功時,將兩者所對應之Wikidata Qid與OpenStreetMap Relation id進行配對,輸出為新檔案compare.csv,且輸出一個已完成串連的檔案already.csv。
  5. 資料的回傳
  6. Wikidata
    • 加上Pid(OSM辨識碼):P402
    • Quickstatements進行上傳 在Wikidata中,Upload資料較為簡單,只需要在compare.csv中,將表格改為column=1為wikidata Qid,column=2為P402,column=3為OpenStreetMap Relation id,在全部複製貼上,即可上傳更新。
  7. OpenStreetMap
    • 回到OSM找原始OSM檔:backfindosm.py 因為要再次開啟JOSM的軟體,重畫範圍等太過麻煩,因此我使用類似queryOSM.py的方法,以要更正的Relation id做搜尋,將每個要更新的Relation id進行搜尋,並下載其osm檔案,即會獲得原始的osm檔案。
    • 將要增加的wikidata Qid加入:inputwiki2osm.py 將所有要加上去的批次加入每一項Relation中。
    • osm->osc:osc.py 將osm的資料轉為osc資料格式,使其OpenStreetMap系統了解使用者是為了更正原始資料。
    • 上傳:upload.py 使用OpenStreetMap原有的開元Uploading檔案,以 ./upload.py -u username -p password -c yes -m 'add wikidata' file.osc執行檔案 可直接執行linkallpy.py,以連動所有步驟程式,再以upload.py進行上傳

並未將upload.py加入串聯是因為要提醒使用者再將大量資料上傳前,需要先進行確認才能上傳。 將資料進行匯入,連動後,以串聯範圍(south,west,north,east)、串聯對象(place_Qid)、串聯國家(country_Qid)、下載路徑作為參數輸入:

./linkallpy.py south west north east place_Qid country_Qid 下載路徑
```執行檔案。
舉例而言,若要串聯台灣地區學校的Wikidata與OpenStreetMap,則學校Qid=Q3914、中華民國Qid=Q865、台灣本島範圍(south,west,north,east)=(22,120,25,122),如下

./linkallpy.py 22 120 25 122 Q3914 Q865 C:\Users\USER\Downloads ```

遇到的困難及可以改進的地方

從串聯的過程中,雖然容易對Wikidata進行串聯,然而在Wikiata資料庫的呈現上仍只有一組識別碼,並非展現出OpenStreetMap的圖層,然而這個部分可能就要與Wikidata的社群討論,是否以OpenStreetMap圖台呈現圖層,更能夠展現出地理特性,畢竟並非所有人都會點入識別碼,連到OpenStreetMap中看地理範圍的。 而在OpenStreetMap中,Relation的數量極少,因此能夠串連的地物不多,且建立Relation的標準不明確,如以中正紀念堂為例,中正紀念堂的Relation範圍在建築物周圍,還是Relation範圍在整個圍牆周圍,這也是需要討論的問題。此外,OpenStreetMap本身在Query時,在bbox的範圍選擇上也容易系統出錯,導致可能查找的範圍並非所求範圍。 另外OpenStreetMap中name的規定有較為不嚴謹,同樣的地物於Wikidata中為全名,在OpenStreetMap中卻為簡稱,因此導致OpenStreetMap中常有名字重複的問題,因此可以以Relation中的Node點座標,對於Wikidata中的點位做距離的比較,即可解決重複問題,然而因為會更為複雜,因此做為之後發展的目標。 除此之外,OpenStreetMap的社群中,對於資料的串聯意見不一,因為有些使用者使用OpenStreetMap不是未開放資料,而是為了個人作業,因此常常會搜尋到很多錯誤的資訊或錯誤的位置,且在於資料補齊上比較無法進行,因為無法確切資訊或錯誤的位置,且在於資料補齊上比較無法進行,因為確定使用者是否接受將資料作為Wikidata的補齊,因此這是兩個社群須溝通的部分。

總結

在此次的研究中,從原本自己一個一個步驟去做串聯,而後將所有步驟一一寫成程式,讓非專業的使用者可以更容易做到兩者的串聯,而其間也閱讀了許多資料,理解到雖然Wikidata與OpenStreetMap皆為開放資料庫,然而兩者性質非常不同,使用者也較為不同,導致在串聯時也常常有技術上或使用上的困難。如在進行作業時,我不只一次與OpenStreetMap社群內的人討論過,這樣做是否是可以的,可謂遊走在灰色地帶,而技術上則是在OpenStreetMap上較容易出狀況,畢竟為開放地圖,並非單純的開放資料庫,也並非皆為純文字,所需要注意的情況也較多。所幸目前大部分的狀況也以找到解法,以自動化串聯程式做為成果,期望這樣的成果與串聯規則能為開放資料做出更多貢獻。