OpenStreetMap logo OpenStreetMap

此文本同時提供 英文版本 This article is also available in English


OpenStreetMap 是一張由和你一樣的使用者共同協作編輯的地圖,這種協作既是它最大的優點,也是資料品質持續出現問題的原因之一。當成千上萬的貢獻者各自為商店、餐廳、診所和政府機關添加 phone 標籤時,每個人都會帶入自己的格式習慣。對臺灣而言,結果就是一個資料庫中同一個國家代碼可能出現 +886+886++886(2),而光是一個城市的電話號碼就可能跨越十幾種不同的慣例。

都亂成一鍋粥了,趁熱喝了吧。(悲

這篇文章記錄了我們在掃描六個直轄市及另外五個縣市的 OSM Elements 時所發現的情況,我們正在開發正規化工具(normalizer) 一勞永逸。


問題的規模

在十一個隨機取樣的區域中——包括所有六個直轄市(臺北市、新北市、桃園市、臺中市、臺南市、高雄市)加上苗栗縣、新竹市、臺東縣、連江縣、金門縣——我們在 49,229 個元素上發現了 49,260 個標籤phonecontact:phone)。在將以分號分隔的多重值欄位拆分後,總共得到 50,643 個獨立的電話號碼字串進行分類。

格式類別 數量 佔比
E.123 空格 (+886 2 1234 5678) 41,842 82.6%
RFC 3966 連字號 (+886-2-1234-5678) 6,655 13.1%
無分隔符號 (+886212345678) 1,158 2.3%
本地格式,無國家代碼 (02-1234-5678) 854 1.7%
錯誤/誤打的國家代碼 (+866 …, +886(2)…) 92 0.2%
其他(錯誤國家、垃圾內容) 42 0.1%

大約 每 5 個獨立值中就有 1 個 偏離了最常見的貢獻者慣例,這種不一致性使得去重(deduplication)、顯示和機器解析變得複雜。

情況從糟糕變成難以理解

各區域的格式分佈有顯著差異:

區域 標籤數 數值數 E.123 RFC 3966 其他
臺北市 ★ 9,804 10,146 85% 11% 4%
新北市 ★ 13,963 14,395 85% 11% 4%
桃園市 ★ 4,177 4,277 83% 12% 5%
臺中市 ★ 8,065 8,282 73% 24% 4%
臺南市 ★ 4,246 4,322 84% 11% 6%
高雄市 ★ 5,168 5,262 84% 10% 5%
苗栗縣 1,318 1,338 77% 18% 5%
新竹市 1,088 1,094 82% 12% 6%
臺東縣 1,101 1,178 96% 3% 1%
連江縣 95 103 98% 0% 2%
金門縣 235 246 90% 8% 2%

★ 直轄市。臺中市以 24% 的 RFC 3966 使用率脫穎而出——大約是其他主要城市的兩倍——這表明該貢獻者社群中存在某種主導的本地編輯模式或工具預設值。離島縣市(連江縣、臺東縣、金門縣)具有最高的 E.123 一致性,可能是因為其較小的貢獻者群體更容易收斂到非正式規範。


何謂「正確」:OSM 的格式標準

在列舉具體問題之前,值得先釐清在 OSM 的脈絡下,「正確」究竟代表什麼。

OSM wiki 的 Key:phone 頁面 並未 強制規定單一格式。它記錄了 ITU E.123 國際標記法、RFC 3966(tel: URI 連字號標記法)以及 NANP 格式,而沒有表達明確的偏好。在實務上,E.123 空格標記法是臺灣貢獻者最常用的格式——這也是為什麼我們將其作為正規化的目標——但 RFC 3966 連字號標記法也是 wiki 明確承認的正當替代方案。

因此,正規化的目標並非嚴格遵守某個強制標準,而是為了 內部一致性:對於編輯者、驗證器和下游使用者來說,所有值都遵循相同慣例的資料集,比隨機混合三種格式的資料集要容易處理得多。

理想的一致格式

對於臺灣,最常見的貢獻者慣用格式是 E.123,其次是 RFC 3966/ NANP (北美地區 +1,類RFC 3966):

ITU E.123
----------------------------------------
+886 2 2034 5678    ← 臺北市話
+886 4 3034 5678    ← 臺中市話
+886 37 203 456     ← 苗栗市話 (3 位數區碼)
+886 89 203 456     ← 臺東市話 (3 位數區碼)
+886 919 114 514    ← 手機
+886 800 000 123    ← 免付費電話 (0800)
NANP
----------------------------------------
+886-2-2034-5678    ← 臺北市話
+886-4-3034-5678    ← 臺中市話
+886-37-203-456     ← 苗栗市話 (3 位數區碼)
+886-89-203-456     ← 臺東市話 (3 位數區碼)
+886-919-114-514    ← 手機
+886-800-000-123    ← 免付費電話 (0800)

多個號碼以分號分隔,末尾不加分號:

ITU E.123
----------------------------------------
+886 2 8787 8787;+886 2 8787 8765

(或)

NANP
----------------------------------------
+886-2-8787-8787;+886-2-8787-8765

Daily struggle meme

小孩才可以全都要,正規化必須作出抉擇

兩者都是可以接受的正規化格式。目前需要社群成員討論的是選擇一種格化並正規化管理,解決混用的問題。


我們的發現

問題 1:不一致的分隔符號

最常見的偏差是混用連字號和空格。這兩者代表的都是同一個號碼:

+886 2 2181 2345     ← E.123(空格,臺灣 OSM 資料中最常見)
+886-2-2181-2345     ← RFC 3966 連字號(正當但較少見)

真正的問題是 在單一數值中混用兩者,這不符合任何一種慣例:

+886 2 2873-6548     ← 國家代碼後用空格,內部用連字號
+886-2-28358739      ← 用連字號,但用戶號碼部分沒有分組

我們發現了 1,554 個數值 在單一電話字串中同時包含空格和連字號——這在任何標準下都是明顯錯誤的。


問題 2:缺少國家代碼

有些貢獻者輸入電話號碼的方式就像他們在本地撥號一樣——沒有 +886 前綴:

02-2581-7780
02 8751 3227
0222346763
0921067050

OSM 的 phone 標籤旨在儲存可國際撥打的號碼。像 02-2581-7780 這樣的值在臺灣以外是具有歧義的:使用者無法知道適用哪個國家的區碼規則。我們發現了 854 個這樣的值,包括直接輸入 09XXXXXXXX 字串的手機號碼。


問題 3:國家代碼後缺少分隔符號

另一種變體是省略了國家代碼與號碼其餘部分之間的分隔符號:

+886288613257
+886228839850

這些在 E.164(電信 API 使用的全數字形式)語法上是有效的,但無法通過大多數顯示驗證器,且作為儲存的 OSM 資料也不易閱讀。我們發現了 1,158 個這樣的值


問題 4:錯誤或畸形的國家代碼

少數但不可忽視的項目包含明顯的輸入錯誤:

+866 2 29126883      ← 數字位置顛倒(應該是 886 而非 866)
+886+2 2311 2940     ← 多餘的加號
+886(2)28232410      ← 帶括號的區碼(北美風格)
+886.2 2322 3477     ← 使用點號作為分隔符
+8886 2 8780 6278    ← 國家代碼中多了一個數字
+00886-2-23825234    ← 前面加了國際撥號前綴 00

我們發現了 92 個這樣的值。這些在任何執行 ITU-T E.164 語法的電話號碼解析函式庫中都會靜默失敗。


問題 5:多重值欄位中的重複項目

OSM 支援使用分號為一個元素儲存多個電話號碼。我們在整個資料集中發現了 1,320 個多重值標籤。其中,24 個包含重複項目——同一個號碼出現超過一次:

+886 2 2916 0300;+886 2 2916 0300
+886 89 862 326;+886 89 862 326;+886 89 862 326

這表明在編輯過程中發生了複製貼上錯誤。雖然本身無害,但它會誇大聯絡選項並干擾去重邏輯。


問題 6:分機號碼——格式大亂鬥

除了主機號碼本身,資料中還有 635 個以上的值 編碼了分機號碼,使用了至少五種不同的慣例:

慣例 範例 數量
井號 # +886 2 2536 3001#8653 572
波浪號 ~ +886 2 2368 0031~2 26
ext. / ext +886 2 2741 5991 ext.21 30
中文 分機 +886 4 2528 5394分機6000 7
逗號 , (iOS) +886 2 2938 2300,630 ~1+

finger pointing meme by @M4HCHE3ZY 冒牌貨!!(指

(@M4HCHE3ZY from X (formerly Twitter))

偵測分機是可行的

正如社群成員在群聊裏指出,一條簡單的規則就夠了:任何不是數字、空格或連字號的字元 ([^\s\d-]) 都可以被視為分機後綴的開頭。這基本上就是我們的正規化工具所做的——在第一個此類字元處拆分,將基礎號碼正規化,然後原樣重新附加後綴。

編碼分機才是問題所在

OSM wiki 的 Key:phone#Extensions 頁面目前記錄了 三種 不同的慣例而沒有從中選出一種,這本身就反映了這個問題多麼懸而未決。

E.123 指定 ext 作為分隔符號。它是在印刷目錄時代標準化的——ext 8653 在名片上清晰易讀,但應用程式無法可靠地解析它。它沒有 DTMF 解釋,分機字串純粹是資訊性質的。

Apple iOS (以及 macOS 聯絡人) 使用逗號 , 作為暫停撥號分隔符號來儲存分機:+886-2-2938-2300,630。逗號指示撥號器在通話接通後等待,然後將剩餘數字作為 DTMF 音頻發送——因此 630 會在主號碼接通後自動撥打。這在設備上是實用的行為,但在 OSM 資料中會產生兩個截然不同的問題:

  1. 與多重值分隔符號的歧義。 OSM 使用 ; 在單個標籤中分隔多個電話號碼。逗號在 OSM 中沒有這種定義好的角色,因此像 +886 2 2938 2300,630 這樣的 iOS 風格數值很可能被誤讀為單個格式錯誤的號碼,而不是號碼加分機。我們在資料集中發現了 16 個帶有逗號的值;大多數是錯誤地用 , 而非 ; 分隔的多個號碼,但至少有一個看起來是真正的 iOS 導出的分機。
  2. 不可移植性。 以逗號編碼的分機僅對支援 DTMF 的撥號器有意義。它不傳達人類可讀的資訊,且對於任何不理解暫停撥號慣例的解析器來說都是不可見的。

libphonenumber 可以偵測多種分隔符號(#extx, 等)後的分機,但不會為分機部分發出規範的輸出格式,而是留給呼叫者處理。

RFC 3966 (tel: URI) 是規範最正式的選項——它使用 ;ext=NNN。但 RFC 3966 的分機語法與 OSM 的資料模型產生了結構性衝突,值得詳述。

RFC 3966 分號衝突

OSM 使用分號 ; 作為 phone 標籤的多重值分隔符號:

+886 2 1234 5678;+886 2 8765 4321    ← 兩個電話號碼,標準 OSM 格式

RFC 3966 的分機語法也使用分號作為參數分隔符號:

tel:+886-2-1234-5678;ext=8653        ← 帶分機的 RFC 3966

如果貢獻者將其儲存在 OSM 標籤中,任何單純在 ; 處拆分的 OSM 編輯器或資料使用者都會將其解譯為兩個值:tel:+886-2-1234-5678ext=8653。分機變成了一支憑空冒出的電話號碼。

顯而易見的解決方法是將分號轉義為 \;,這是一些 OSM 標籤對數值內字面分號使用的慣例。但這會產生自己的問題:

  • OSM 編輯器 並不一致地支持 \; 轉義;許多編輯器仍會在該處拆分或直接顯示轉義符。
  • RFC 3966 解析器 期望原始的 ; 作為參數分隔符——反斜槓轉義的 \;ext=8653 不是有效的 RFC 3966,且不會被任何符合規範的 tel: URI 解析器正確解析。
  • 機器可讀性 並未提高:使用者現在需要同時了解 OSM 的反斜槓轉義慣例 以及 RFC 3966 的參數語法,並調和兩者。它增加了編碼複雜性,卻沒有給任何解析器一條清晰的路徑來獲取分機數字。

反斜槓轉義是一個漏洞百出的解決方法,無法完全滿足任何一個標準。實際上,它是疊加在兩個已經衝突的編碼之上的第三種編碼。

結果就是 RFC 3966 分機標記法與 OSM 的分號作為多重值慣例在結構上不相容,目前沒有完美的解決方案。出於這個原因,我們的正規化工具會原樣保留分機後綴,而不是嘗試將其重寫為任何標準形式。


E.123 與機器可讀性

有件事值得特別說明:即使是 完美 正規化的 E.123 電話標籤,也不像看起來那麼對機器友善。

E.123 是由 ITU-T 在 1988 年標準化的——當時電話號碼的主要媒介是名片、信頭或印刷目錄。+886 2 1234 5678 中的空格是為人類讀者提供的視覺分組輔助,而非語義標記。遇到該字串的解析器必須去除空格、推斷國家代碼並找出區碼邊界——這一切都是靠啟發式方法完成的。

RFC 3966 的 tel:+886-2-1234-5678 結構稍微好一點(連字號作為顯式分隔符號,URI 方案標示「這是一個電話號碼」),但仍需要真正的解析器來解譯數字分組。真正對機器友善的形式是 E.164——+886212345678,全數字,無標點符號——這才是電信 API 和資料庫真正需要的。而這些都不是 OSM 預設儲存的格式。

問題的根源說到底,是個無法迴避的矛盾::OSM 的 phone 標籤是面向人類的。正規化為 E.123 是為了讓資料對貢獻者來說保持一致且易於編輯,而不是為了產生一種應用程式可以直接使用而不需解析的格式。下游應用程式仍然需要像 libphonenumber 這樣的函式庫來完成實際工作——這也正是為什麼該函式庫對於臺灣邊緣案例區碼的正確性至關重要。


google/libphonenumber 微妙的區碼分組方式

非常好的專案,使我大腦旋轉。Google 的 libphonenumber——幾乎所有電話號碼解析器使用的標準函式庫——對某些臺灣區碼的分組方式,與本地使用慣例有所不同。這個問題相當微妙。

臺灣的公眾電信網路號碼計畫分配了數組 3 位數和 4 位數的區碼。libphonenumber 的元資料似乎將這些區碼表示為其 2 位數鄰居的延伸,產生了與本地慣例不同的分組方式:

撥號 libphonenumber 輸出 預期輸出(E.123)
037-123-456 +886 3 7123 456 +886 37 123 456
049-123-4567 +886 4 9123 4567 +886 49 123 4567
082-123-456 +886 8 2123 456 +886 82 123 456
0826-12345 +886 8 26123 45 +886 826 12345
0836-12345 +886 8 36123 45 +886 836 12345
089-123-456 +886 8 9123 456 +886 89 123 456

受影響的地區:苗栗 (037)南投 (049)金門 (082)烏坵 (0826)馬祖/連江 (0836) 以及 臺東 (089)

這意味著即使是已經以 +886 X XXXX XXXX 形式儲存的電話號碼,如果是透過使用 libphonenumber 的工具輸入的,也可能帶有不同的數字分組。本文所採用的分組方式依據「公眾電信網路號碼計畫」及公部門聯絡方式標示——不過這也可能是 libphonenumber metadata 的刻意設計。

另見:


關於 OpenStreetMap 臺灣

OpenStreetMap 臺灣由台灣關心投入 OpenStreetMap 的編輯者構成,自從 2010 年開始由個人獨自編輯變成集結更多人參與的共編地圖專案的在地社群。目前在台灣有在台北與 Wikidata 社群共同舉行 OpenStreetMap x Wikidata 月聚,以及不定期的踏查活動。




2026年3月30日(星期一)
臺灣時間16時15分

最後更新於2026年4月1日(星期三)
臺灣時間12時00分

NNNN

Location: 黎明里, 中正區, 台北站前商圈, 臺北市, 臺灣

Discussion

Comment from DanhengOSM on 30 March 2026 at 09:01

首先感谢这篇非常系统、扎实的整理。无论是数据抽样、问题分类,还是对 E.123 / RFC 3966 / E.164 之间关系的梳理,都对理解 OSM 电话标签的现状很有帮助。

从中国大陆社群的角度,此处大体有几点共识,供参考:

1)尊重并理解台湾社群的在地决策 电话格式在很大程度上属于“本地数据治理问题”,与编辑习惯、工具使用乃至社区规模都有关系。既然 E.123 已经在中国台湾数据中形成事实上的主流(de facto standard),推动向该格式收敛,是一个合理且务实的选择。

2)现阶段不存在“一套覆盖两岸四地的统一最终方案” 不同地区在电话号码结构、使用习惯、历史数据积累,以及社区共识上都存在差异。在缺乏跨区域强共识和统一工具链的情况下,强行制定一个“全域标准”反而可能带来更多摩擦和回退编辑。因此,分区域收敛、逐步改善数据质量,可能是更现实的路径。

3)支持中国台湾社群推进 E.123 正规化,并建议扩大交流 将格式统一为 E.123(空格分组)有明显优势:

  • 已是多数数据的自然形态
  • 对人类可读性友好
  • 对编辑器与验证工具的适配成本较低

如果后续有进一步的规范草案或自动化工具(normalizer),也很欢迎在 OSM 跨区域讨论区分享,让包括中国大陆在内的更多使用者参与讨论,看看是否有可借鉴之处(例如在数据清洗、分机处理策略等方面)。

4)关于国家代码问题的一个务实建议 电话国家码本质上属于 ITU 体系下的电信标识。在当前阶段,为了避免非技术性因素影响数据整理工作,我们倾向于将其视为“既有事实数据的一部分”来处理:

  • 中国大陆地区继续使用 +86
  • 中国台湾地区使用 +886

先在各自范围内实现格式一致性与数据可用性,再讨论更高层级的统一问题,可能更有利于实际推进。


总体来说,您的报文已经很好地指出了问题的关键:

与其纠结“哪种格式最正确”,不如先解决“数据是否一致可用”。

期待看到社群后续的正规化工具和实践成果,如果有需要跨区域测试或对比数据的地方,也欢迎交流。

Comment from assanges on 30 March 2026 at 10:34

承蒙閣下厚愛,感謝如此完整、周到的回應,字裡行間可以感受到滿滿的善意。仁者見仁,智者見智,千人千面,各有所見,固無可厚非——然明月從來只有一輪。以下補充,期望未來交流能更順暢。

首先,非常榮幸獲得閣下的「理解與尊重」,理性務實。注意到這份尊重在開首便以「中國台灣」的形式呈現——想必這此乃無心習慣,畢竟在技術討論中摻雜政治立場,應不是有意為之。如此開場多少影響了後續的善意感受,就不在此多加闡述。

關於跨區域統方案的想法:感謝閣下的宏觀視角。不過稍作說明,臺灣社群並未提出這樣的需求,也沒有這樣的打算。本次討論的重點是整理臺灣在地資料的現況,並非尋求任何形式的「最終方案」。閣下的提議不僅超出本次討論的範圍,亦非 OSM 一貫的運作方式,毌須在此重新發明輪子。若欲討論範疇以外的資料,建議閣下另開新篇,以免喧賓奪主。

關於工具與開放協作:正規化工具預計會在適當時機開源,屆時歡迎所有人參與貢獻,當然也包括閣下。開源社群的規則很簡單——用 PR 說話,用 issue 說話,用資料說話。非常期待良性的互動交流,歡迎閣下利用該工具正規化 +86 的資料。

關於 +886 的「務實建議」:感謝閣下確認臺灣的國碼是 +886,這確實是非常寶貴的資訊。臺灣使用 +886 是不爭的事實,在地人一直以來都是這樣認知的。很高興我們在這一點上達成了共識。

真誠地歡迎所有建設性的參與——只願同席諸位,皆為資料而來,別無旁騖。

敬祝編輯愉快。

Leave a comment

Log in to leave a comment