免費的方法優先

你的照片早就知道你去過哪些國家

寫於 2026 年 9 月 21 日,更新於 9 月 23 日  ·  撰文:Aki Takashima(Shiori Studio)

幾乎沒有人會把自己去過的國家列成清單。但幾乎每個人都有十年份的照片。只要是開著定位服務拍的照片,都帶著拍攝地點的座標,由相機寫進檔案裡。所以那份清單其實早就存在了,只是散落在你的圖庫各處,要做的只是把它取出來。

這一頁寫的是完整的方法:在手機上兩分鐘完成的免費做法、能產生真正的國家與日期清單的免費命令列做法,以及各種會出錯的情況。最後這一部分才是有意思的地方,也是你第一次算出來的答案會出錯的原因。

首先,確認你的照片到底有沒有位置資訊

在「照片」App 裡打開任何一張照片,往上滑。如果照片下方有地圖,這個檔案裡就有座標。如果沒有地圖,就是沒有座標;任何工具都無法憑空生出一個,我做的工具也不例外。

通常沒有位置資訊的:螢幕截圖、從通訊 App 和網頁存下來的圖片、相機的「定位服務」關閉時拍的照片,以及分享時被手動移除位置的照片。通常會有位置資訊的:用 iPhone 相機本身拍的照片與影片,以及大多數能連接手機的新型相機拍的照片與影片。

在 iPhone 上兩分鐘完成的做法

「照片」→「圖庫」→選單按鈕→「顯示地圖」。Apple 在 iPhone 使用手冊裡說明了這個步驟,也寫出了唯一重要的限制:只有內嵌位置資料的照片和影片才會納入。

現在你有了一張插滿圖釘的世界地圖,看了確實很有成就感,但幾乎什麼問題都沒回答。它不會告訴你總共有幾個國家、每個國家是什麼時候去的,也不會告訴你每個圖釘屬於哪一趟旅程。要知道這些,就得把數字取出來。

不用安裝任何東西的做法

我做了一個免費的網頁,可以替你完成下一節的工作:counter.getdriftlog.com(英文)。把照片、一整個匯出的資料夾、解壓縮後的 Google 匯出(Google Takeout)資料夾,或 Google 地圖時間軸的匯出檔(英文)丟進去,它就會列出國家,以及每個國家最早與最晚出現的年份,並畫在一張可以儲存的地圖上。它只讀取中繼資料,完全在瀏覽器裡執行,不會上傳任何東西;頁面載入完成後,就算關掉 Wi-Fi 也能繼續使用。它也能在 iPhone 的 Safari 裡執行;只要照片選擇器顯示「包含位置」,選擇器就會把位置資訊一併傳過去。

如果你想要原始的座標,或是想要精確到日而不是到年的日期,下面的命令列做法還是值得了解。

能列出真正國家清單的做法

這個做法在 Mac 或 PC 上執行,第一次大約要十五分鐘,不用花錢,而且絕不會把照片上傳到任何地方。共三個步驟。

步驟 1

輸出原始檔

在 macOS 的「照片」App 裡選取全部照片(「編輯」→「全選」),然後使用「檔案」→「輸出」→「輸出未修改的原始檔」。請輸出到一個空的資料夾。重點是要輸出未修改的原始檔:編輯過的照片在輸出時可能會重新編碼,而位置資料就是在重新編碼的過程中遺失的。

如果你的照片本來就放在硬碟的資料夾裡,這個步驟可以整個跳過。

步驟 2

用 ExifTool 把座標取出來

ExifTool 是免費的工具,你手上可能有的格式它都讀得了,而且只讀取時不會更動任何東西。一行指令就能把一個資料夾的照片,變成一份座標與日期的 CSV:

exiftool -r -m -q -f -n \
  -if '$gpslatitude' \
  -p '$gpslatitude,$gpslongitude,$datetimeoriginal' \
  ~/Desktop/photo-export > coords.csv

-r 會連子資料夾一起處理,-if 會略過沒有 GPS 資訊的檔案,-n 會輸出單純的十進位度數,而不是美化過的格式;-f 則會在檔案沒有原始拍攝日期時印出一條短橫線(-),而不是把那一行丟掉。就算圖庫有好幾萬個檔案,這也只要幾分鐘,不用幾小時,產生的內容大致像這樣:

33.9850,-118.4695,2026:08:31 14:06:22
35.6595,139.7005,2025:04:02 09:11:47
-
步驟 3

離線把座標轉成國家名稱

你不需要 API 金鑰,也不應該為了查這個,就把自己的一萬筆座標傳給某個網路服務。在本機查詢就夠了:

pip install reverse_geocoder
import csv, collections
import reverse_geocoder as rg          # 離線查詢:資料集隨套件附帶

rows = [r for r in csv.reader(open("coords.csv")) if len(r) >= 2]
pts  = [(float(r[0]), float(r[1])) for r in rows]
hits = rg.search(pts, mode=1)

days = collections.defaultdict(set)    # 國家代碼 -> 日期的集合
for row, hit in zip(rows, hits):
    stamp = row[2] if len(row) > 2 else "-"
    day   = stamp[:10].replace(":", "-") if stamp != "-" else None
    days[hit["cc"]].add(day)

for cc, d in sorted(days.items(), key=lambda kv: -len(kv[1])):
    print(f"{cc}\t{len(d)} 天有照片")

這會印出你去過的國家,並依「有照片可以證明你在那裡」的天數排序。大家寫在個人簡介裡的那個數字,這才是它老實的版本。

會讓這個答案出錯的五件事

前三項今天就會出現在你的 CSV 裡。這個問題之所以比看起來難,原因就是這五項。

1. 上面的查詢找到的是最近的城鎮,不是你當時所在的國家

reverse_geocoder 會把你的座標對應到它的資料集裡最近的有人居住的地點。在離國界十公里的地方,或是在外海的任何位置,最近的城鎮可能在隔壁的國家。解決辦法是拿行政邊界檔來做真正的「點在多邊形內」判定;常見的免費選擇是 Natural Earth 的 admin-0 資料集。但要注意,低解析度的版本偏偏就在你最需要精確度的海岸線和飛地上,把細節簡化掉了。

2. 在空中拍的照片,會多出你從未入境的國家

在巡航高度從靠窗座位拍的照片,是一筆完全有效的 GPS 定位,只是位置落在你飛越而沒有降落的國家上空。最近城鎮的查詢方式會毫不猶豫地把它歸給那個國家。如果你想要一份站得住腳的清單,就把在時間和空間上都孤立的定位點拿掉,也就是離當天其他定位點有幾百公里遠、前後又都沒有其他紀錄的單獨一點;或者在 EXIF 有記錄高度的情況下,用高度來篩選。

3. EXIF 的時間戳記沒有時區

DateTimeOriginal 記的是當地時鐘上的時間,卻沒有附帶任何資訊說明是哪一個時區的時鐘。較新的檔案還會帶有 OffsetTimeOriginal,較舊的檔案通常沒有。因此依日期分組時,旅程的頭尾兩端最多可能各差一天。如果你算的是天數,這影響非常大;如果你算的是國家數,就完全沒有影響。

4. 照片很難準確地分成一趟趟旅程

直覺的做法,是依間隔把一串帶日期的定位點切成一趟趟旅程:離開 N 天,或移動 M 公里之後,就當成新的一趟。這兩種門檻都會失靈。假期中間有一天沒拍照,一趟旅程就被切成兩三趟。一次轉機變成去過一個國家。長期旅居國外期間回家過一個週末,又把一切重新切開。

5. 你住的城市會把一切都淹沒

大多數人的照片,絕大部分是在自己住的地方拍的。除非你排除住家周圍一定半徑內的範圍,否則輸出的清單裡,有意思的項目會被埋在好幾千筆離你家門口不到五公里的定位點底下。

如果你寧可自己寫程式,在手機上處理

如果你打算自己寫程式來做,而不是執行現成的指令碼,Apple 的 PhotoKit 有一個細節值得知道:PHAsset 會直接提供每個項目的位置,所以你可以走訪整個圖庫、讀取座標與日期,卻連一張圖片都不必解碼。這就是照片匯入在手機上可以幾秒鐘就完成的原因,也是它完全不需要照片內容的原因。

另一半的關鍵是權限。如果圖庫的取用權限受到限制(也就是「所選的照片」這個選項),你只看得到使用者挑選的那些照片,重建出來的結果會少算,而且不會有任何提示。如果你正要開發這樣的功能,Apple 自己寫的照片 App 隱私權指引是最好的起點。

如果這些你都不想自己動手

利益揭露。Driftlog 是我做的。這款 iPhone 與 Android App 會做上面這些事,然後繼續做下去:它讀取你現有照片裡的位置資料來重建過去的旅程;從現在起,它也會在 App 關著時,利用手機精度較粗的「顯著位置變更」訊號,記下你經過的國家、地區與城市。一次購買 US$6.99,沒有訂閱、沒有廣告、不用帳號;免費版完整開放你居住的國家和你的第一個外國,之後的每個國家也照樣會填到地圖上。它可以在 iOS 17 或以上版本的 iPhone 與 iPad 上執行;Android 版則從 Google Play 下載。

它的限制也一併說清楚:它只讀取照片的中繼資料,絕不讀取影像本身;照片匯入需要允許取用所有照片,而且只看得到帶有位置資訊的照片;它記錄的是地點,不是路線;即時記錄需要把位置權限設為「永遠」並開啟「準確位置」;座標會離開手機、被換成地名,這是它唯一會對外發出的請求;另外,這一頁提到的每一種出錯情況,在它身上同樣會發生,只是它內建了我為了處理這些情況所做的各種嘗試。

在 App Store 查看 Driftlog

Android 版:Google Play

這個方法找不回來的東西

歡迎指正。如果這裡的某個指令在你的系統上無法執行,或是某個步驟已經改了,請寄電子郵件到 shiori.sutudio@gmail.com,我會修正頁面並更新日期。