2015年7月22日 星期三

csv 轉 geojson : 大批地址匯入你的私房地圖

中華電信臺中直營門市地圖 手中有一串地址 (例如某連鎖店), 想把這些地點加入你自製的私房地圖嗎? 先把它變成 csv 檔 -- 也就是 LibreOffice Calc 或 Microsoft Excel 之類軟體能夠讀寫的純文字版試算表檔案格式, 然後按照本文步驟, 不必寫程式 (因為別人和我已經幫你寫好了) 只要下幾個指令, 就可以把這些地址變成你的 umap 或 mapbbcode 私房地圖上的地標囉! 又, 如果你手邊的地址本來就是存在 ods 或 xls 或 xlsx 檔裡面, 也請先把它改存成 csv 格式。

([2015/10/13] 發現另一條路: 先用 csvtojson 再用 jq 兩階段轉檔。但本文不談。)

[2017/6/15: 捷安特的網站介面改變, 原文已不適用。 改用中華電信作例子; 保留捷安特的中間步驟檔。] 假設我們想自製某連鎖店的店面地圖。 先搜尋到官網 ( 中華電信門市/ 捷安特官網), 按照縣市鄉鎮或分店/據點類別撈出帶有分店名稱及地址的資訊, 把整片搜尋結果剪貼到文字檔內, 類似這樣: [ 中華電信臺中市直營服務中心 cht.txt / 捷安特提供租賃服務的店面 giant.txt]。

如果兩筆記錄之間已經有空列隔開 (例如 giant.txt), 等一下就可以直接用 perl 的 -000 (下詳) 來處理資料。 如果沒有, 就要先在每筆的第一列之前, 或每筆的最後一列之後插入空列, 例如 cht.txt: p -pe 's/直營服務中心//' cht.txt > cht1.txt (原始的 cht.txt 多了兩個不該有的空列, 已事先手動刪除。)

再來把它轉成試算表格式, 順便把地址欄整理乾淨, 不要有多餘的字元。 (啊,後來才發現郵遞區號好像可以留著沒關係~~ 對不起啊, 郵差先生!)
中華電信: perl -000 -pe 's/\n/,/g; s/地址\s*\d+//; print "\n"' cht1.txt > cht.csv
捷安特: perl -000 -pe 's/\n/,/g; print "\n"' giant.txt > giant.csv
這裡的 -000 叫 perl 以段落而非以列為單位來處理資料 -- 兩筆資料當中不是以一個換列而是以一個空白列 (也就是兩個換列) 隔開。

插入空白格以便對齊欄位 然後用 libreoffice 開啟 csv 檔。 有少數地方可能需要手動調整, 例如中華電信的日南、 機場、 梨山三個服務中心因為某個欄位是空的, 所以需要用 「insert」 => 「shift cells right」 將後半段往右移, 才會對齊。

再把地址欄位剪貼到李小淮大大的 輸入地址批次轉換經緯度小工具 頁面, 產生經緯度。 我喜歡勾選 「加上地址」, 這樣等一下要合併檔案時, 還可再次確認跟原始資料確實每列對齊。 如果那個網站過熱無法使用, 那就改用需要註冊、 較麻煩的 TGOS 服務

找出經緯度之後, 把輸出結果貼在另一個文字檔, 叫做 coords.csv 好了。 用文字編輯器把所有 "=" 變成 ","、 存檔、 離開。 再用先前的試算表軟體開啟 coords.csv。 把它剪貼補到 giant.csv 右邊、 對齊好、 刪掉多餘的地址欄、關掉 coords.csv。

繼續在試算表裡面編輯 giant.csv。 在最上方補一個空白列, 用英文字母/底線/數字的組合替每一欄取一個名稱。 經度欄一律固定叫做 lon 或 longitude; 緯度欄一律固定叫做 lat 或 latitude。 另外, 大力建議把店名欄取為 name, 因為固定就是 name 欄會被某些程式顯示出來。 其他欄位只是參考用; 不要的欄位可以刪掉。 其實你的資料裡面如果有空白列, 或是 # 開頭的註解列也 OK, 等一下這些列都會被略過。 最後類似這樣: [cht.csv / giant.csv]

然後把 csv2geojson.perl 存檔改名為 csv2geojson, 並且 chmod a+x csv2geojson 變成可執行檔, 放到 /usr/bin 底下。 於是就可以執行 csv2geojson giant.csv > giant.geojson 產生 geojson 版的租車店家地址/座標等等資訊。 如果你曾經在 umap 裡面編輯地圖、 修改顏色及圖案、 把資料匯出成 geojson 格式, 就會知道要如何設定你的 geojson 檔。 例如我先手動把一兩個圖徵的圖案換成腳踏車、 把顏色換成捷安特他們公司的藍色, 匯出之後得知需要在物件的 properties 欄位裡面加上 _storage_options 欄, 像這樣: (不用擔心, 這跟寫程式無關; 只是讓你看一下我們心中想產生的檔案該長什麼樣子。)

  {
    "type": "Feature",
    "geometry": {
      ...
    },
    "properties": {
      ...
      "_storage_options": {
        "iconClass": "bicycle",
        "color": "#0061d4",
        "iconUrl": "/uploads/pictogram/bicycle-24-white.png"
      }
    }
  }

所以再用 jq 幫 giant.geojson 整修一下即可。

我把上面兩步 (「csv=>geojson」 以及 「加上圖案及顏色」) 合併成一步如下: csv2geojson giant.csv | jq 'map(.properties+={_storage_options:{iconClass:"bicycle",color:"#0061d4",iconUrl: "/uploads/pictogram/bicycle-24-white.png"}})' > ~/giant.json

最後上傳到 umap 上, 就大功告成囉! 暑假可以來規畫一趟 「單車與大眾運輸之旅」 耶! (聽說捷安特可以甲地租乙地還。) 另外, 想要就近找中華電信的服務中心, 改用 中華電信台中市各服務中心地圖 是不是比官網更方便呢?

隱私警告: 如果是同學/朋友/員工/客戶/...的住家地址, 可別亂上傳, 否則會觸犯個人資料保護法哦! 雲端沒有隱私, 即使設了密碼也不一定安全; 但如果一定要冒險上傳, 至少請在 umap 上把你的私密地圖設定成不公開。

沒有留言:

張貼留言

因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。