把整串地址丟進來就好
tw-fuzzy-zipcode
從沒有拆欄位的台灣地址查郵遞區號,並依中華郵政的規則翻成英文地址。台/臺、全半形與中文數字都認得,缺了縣市或行政區也能查;所有查詢都在用戶端完成,不需要伺服器、WASM 或 SQLite。
IDEA
辨識整段文字
表單裡的地址不一定拆得乾淨:使用者貼上的原始字串、OCR 結果、舊系統留下的單一文字欄位,都是一整串。tw-fuzzy-zipcode 直接吃這種地址,不要求先拆成縣市、鄉鎮市區與路名。它是 moskytw/zipcodetw 比對演算法的 JavaScript 改進版,沒有任何執行期相依套件。
FUZZY MATCHING
怎麼寫都認得
先正規化台/臺、全半形與常見中文數字寫法,再把地址切成縣市、行政區、路段、巷弄與門牌片段逐層比對。資訊夠就依門牌規則回傳 6 碼,不夠就退回可用的 3 碼;含糊不清時會回空字串,不會亂猜。
臺北市信義區市府路1號
完整地址依門牌規則比對,回傳 6 碼。
台北市秀山街
「台」自動正規化為「臺」,只寫到路名也查得到。
松山區
只給行政區時,回傳可用的 3 碼。
松江路100號
路名全臺唯一,自動補回缺少的縣市與行政區。
UNIQUE ROAD
少寫的部分,替你補回來
地址省略縣市或行政區時,若剩下的寫法在全臺只對應到一條路,就把缺的片段補回去再繼續比對到 6 碼。對應到無法猜測的多條同名路時(例如到處都有的中正路),也不會亂補。
輸入
松江路100號
↓
自動補齊
臺北市中山區松江路100號
104091
SPEED
查一次不到 2 微秒
瀏覽器用的索引把排序後的資料依欄位攤平成字串,另存 Int32Array 偏移量以二分搜尋查找。只需四分之一的記憶體,每秒可執行約 50 萬次查詢。
1.7–2.0 µs
單次查詢
34 ms
瀏覽器載入資料索引
0.80 MB
Brotli 傳輸大小(gzip 約 1.21 MB)
5.3 MB
載入後記憶體(瀏覽器)
資料集為中華郵政 2026 年 6 月的 3+3 郵遞區號,含 79,845 條門牌規則與 162,470 筆漸進式地址。與 Python 參考實作進行 90,950 筆差異測試,結果零差異;量測環境為 Apple M3 Pro。
基隆愛三路郵局第5號信箱
P.O. Box 5, Keelung Ai 3rd Road, Keelung City 200900
P.O. BOX
郵政信箱也查得到
「OO郵局第 N 號信箱」不是門牌,郵遞區號由郵局名稱直接對照得出,不經過門牌規則。共涵蓋 899 個實際開辦信箱的郵局;來源資料另有 314 個已配賦六碼、但尚未開辦信箱的郵局,一律回傳空字串。
ENGLISH ADDRESS
順便翻成英文地址
依中華郵政的書寫規則反轉語序、補上郵遞區號,翻出可以直接印在信封上的英文地址。所有名稱都取自官方中英對照。
臺北市中正區忠孝東路一段1巷1弄1號1樓
1F., No. 1, Aly. 1, Ln. 1, Sec. 1, Zhongxiao E. Rd., Zhongzheng Dist., Taipei City 100009, Taiwan (R.O.C.)
樓、號、弄、巷、段逐層對應官方縮寫,郵遞區號自動查好帶入。
政大郵局第12號信箱
P.O. Box 12, National Chengchi University, Taipei City 116979, Taiwan (R.O.C.)
郵政信箱的英文局名同樣來自官方資料,欄位換成 P.O. Box 與局名。
臺北市信義區四維三路2號
english: ''
四維三路其實在高雄市苓雅區,信義區沒有這條路會回傳空字串。
OPEN SOURCE
MIT 開源授權,隨意使用
發布的就是純 JS,無需建置,瀏覽器可以直接載入。若使用 TypeScript,也內含型別宣告,不必另外安裝 @types。資料分成門牌索引、信箱表與中英對照三份彼此獨立的字典。
郵遞區號、中英對照與郵局專用信箱資料皆來自中華郵政,依其「3+3 郵遞區號公開授權聲明」與政府資料開放授權條款使用。比對演算法參考自 moskytw/zipcodetw。
USAGE
怎麼用
零相依,純 JS 寫成,Node 端 import 進來就能查。瀏覽器沒有存取檔案,需要用 loadZipcode() 載入隨套件發布的資料檔。內建型別宣告,不必另外安裝 @types。
TERMINAL
$ npm install tw-fuzzy-zipcodeNODE.JS
import { find, lookup, translate } from 'tw-fuzzy-zipcode'find('臺北市信義區市府路1號')// '110204'find('松江路100號')// '104091',路名全臺唯一,縣市與行政區可以省略lookup('臺北市')// { zipcode: '1', source: 'gradual', resolution: 'prefix' }translate('臺北市信義區市府路1號').english// 'No. 1, Shifu Rd., Xinyi Dist., Taipei City 110204, Taiwan (R.O.C.)'
BROWSER
import { loadZipcode } from 'tw-fuzzy-zipcode/browser'// 瀏覽器沒有 fs,改用 loadZipcode() 載入隨套件發布的資料檔const zip = await loadZipcode({gradualUrl: '/data/gradual.tsv',preciseUrl: '/data/precise.tsv',mailboxUrl: '/data/mailbox.tsv',})zip.find('臺北市信義區市府路1號')// '110204'
常用 API
find(address)回傳可直接使用的 3 或 6 碼郵遞區號;查不到或無法確定時回空字串,不會給無效的 4/5 碼中間前綴。
lookup(address)需要顯示比對層級時用它,回傳 { zipcode, source, resolution },找不到則為 null。
findAddress() / findMailbox()只查門牌或只查郵政信箱的子函式。資料來源確定只有一種形式時可以省去另一種比對。
translate(address)回傳 { english, parts, untranslated, complete };郵遞區號會自動查好帶入,也可用 { zipcode } 自行指定。
loadZipcode({ gradualUrl, preciseUrl, mailboxUrl })瀏覽器端載入資料檔並建立 Zipcode,方法名稱與上面的函式相同。三份字典各自獨立,只載需要的那幾份。
loadTranslator({ roadUrl, districtUrl })瀏覽器端的中英對照,可接上 verify 與 mailbox 做路名交叉驗證與信箱英譯。
lookup() 的回傳值
sourceprecise · gradual · mailbox
郵遞區號的來源:依門牌規則比對、依漸進式地址索引,或依郵政信箱對照表得出。
resolutionsix-digit · three-digit · prefix
解析到的層級:精確至 6 碼、3 碼,或僅辨識到縣市等前綴(不足以構成有效郵遞區號)。