Deterministic, offline Malaysian address parser (A1/A2/A3/Postcode/State) for messy real-world datasets.
Project description
Malaysian Address Parser
Deterministic, rule-based Malaysian address normalization engine built for messy real-world datasets.
This package extracts and standardizes Malaysian address strings into structured components:
ALAMAT1 | ALAMAT2 | ALAMAT3 | POSTCODE | STATE
Designed specifically for:
- Noisy Excel exports
- Local council datasets
- Mixed-format government records
- Inconsistent commas & whitespace
- Postcode false positives (LOT/PT/NO patterns)
✨ Features
- ✅ Rule-based (no ML dependency)
- ✅ Offline-capable
- ✅ Canonical Malaysian state mapping
- ✅ False-positive postcode protection
- ✅ MELAKA TENGAH special case handling
- ✅ CLI tool
- ✅ Excel batch processing
- ✅ Unit-tested (pytest)
- ✅ CI-enabled (GitHub Actions)
📦 Installation
From PyPI (if published)
pip install malaysian-address-parser
Local Development
pip install -e ".[dev,excel]"
Optional extras:
[excel]→ Excel processing (pandas + openpyxl)[pdf]→ PDF extraction (camelot)[dev]→ pytest + ruff
🚀 Usage
1️⃣ Parse Single Address (CLI)
malaysian-address-parser parse-one "Lot 123, Jalan Bunga, Taman Mawar, 70400 Seremban, Negeri Sembilan"
Pretty output:
malaysian-address-parser parse-one "..." --pretty
Example Output
{
"alamat1": "LOT 123 JALAN BUNGA",
"alamat2": "TAMAN MAWAR",
"alamat3": "SEREMBAN",
"poskod": "70400",
"negeri": "NEGERI SEMBILAN DARUL KHUSUS"
}
2️⃣ Parse Excel File
malaysian-address-parser parse-excel input.xlsx --col address --out output.xlsx
Options
| Flag | Description |
|---|---|
--sheet |
Sheet name or index |
--col |
Column containing raw address |
--out |
Output file (.xlsx or .csv) |
--limit |
Limit rows (debug mode) |
--no-keep-original |
Output only parsed fields |
Example:
malaysian-address-parser parse-excel data/input.xlsx --col SEMASA_ALAMAT_RAW --out results/parsed.xlsx
Supports:
- Relative paths
- Absolute paths
- Auto-creates output directory if missing
🧠 Python API Usage
from malaysian_address_parser import classify_address_v2
address = "Lot 123, Jalan Bunga, Taman Mawar, 70400 Seremban, Negeri Sembilan"
a1, a2, a3, poskod, negeri = classify_address_v2(address)
print(a1)
print(a2)
print(a3)
print(poskod)
print(negeri)
📂 Project Structure
.
├── src/
│ └── malaysian_address_parser/
│ ├── classifier.py
│ ├── alamat_splitter.py
│ ├── postcode_state_extractor.py
│ ├── pre_cleaner.py
│ ├── normalizer.py
│ ├── cli.py
│ └── excel_runner.py
│
├── tests/
│
├── .github/workflows/ci.yml
├── pyproject.toml
└── README.md
🔍 Core Logic Highlights
Prefix Splitting
Splits prefix into:
- ALAMAT1 (A1) → Unit + Street
- ALAMAT2 (A2) → Area (Taman, Kampung, PPR, etc.)
Uses keyword-based heuristics instead of naive comma splitting.
Postcode Detection
- Detects valid 5-digit Malaysian postcodes
- Ignores false positives like:
LOT 54321
PT 12345
Scoring system prefers postcodes appearing toward the end of address.
State Canonicalization
Recognizes all Malaysian states including ceremonial names:
- JOHOR DARUL TAKZIM
- PERAK DARUL RIDZUAN
- SELANGOR DARUL EHSAN
- etc.
All states normalized into canonical format.
Special Case Handling
Protected case:
MELAKA TENGAH
Prevents accidental stripping of "MELAKA" during state extraction.
🧪 Testing
Run tests locally:
pytest -q
CI runs tests across:
- Python 3.10
- Python 3.11
- Python 3.12
- Python 3.13
⚠ Known Limitations
- Extremely ambiguous rural addresses may require manual review
- No postcode ↔ state validation yet
- No gazette-level mukim verification
- Fully rule-based (no ML fallback)
🔮 Roadmap
- Postcode ↔ State validation layer
- Mukim-level canonical validation
- Performance benchmarking (rows/sec)
- Parallel Excel processing
- Docker packaging
- Web interface wrapper
🎯 Intended Use Cases
- Local authority datasets
- Asset registers
- CRM normalization
- Data migration projects
- License databases
- Cukai taksiran records
- Address standardization pipelines
📜 License
MIT
Maintainer
Imaduddin
Built for real Malaysian address data.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file malaysian_address_parser-0.1.1.tar.gz.
File metadata
- Download URL: malaysian_address_parser-0.1.1.tar.gz
- Upload date:
- Size: 13.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
288b40a956f3cb564264a2b4519cde8b1422854eaa4fbcf80d0c01d7e0f43a8b
|
|
| MD5 |
460be1e10310a239a895e51941fb7661
|
|
| BLAKE2b-256 |
ca14e1e0da4f6343e7dee55f524811d0b7e3029482774e33f8267d0ffa0651e7
|
Provenance
The following attestation bundles were made for malaysian_address_parser-0.1.1.tar.gz:
Publisher:
release.yml on imad210/MALAYSIAN_ADDRESS_PARSER
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
malaysian_address_parser-0.1.1.tar.gz -
Subject digest:
288b40a956f3cb564264a2b4519cde8b1422854eaa4fbcf80d0c01d7e0f43a8b - Sigstore transparency entry: 1018778335
- Sigstore integration time:
-
Permalink:
imad210/MALAYSIAN_ADDRESS_PARSER@2c9c364b21e2defaca7f6f7a5cb9528d7e3a1300 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/imad210
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2c9c364b21e2defaca7f6f7a5cb9528d7e3a1300 -
Trigger Event:
push
-
Statement type:
File details
Details for the file malaysian_address_parser-0.1.1-py3-none-any.whl.
File metadata
- Download URL: malaysian_address_parser-0.1.1-py3-none-any.whl
- Upload date:
- Size: 12.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9bf21268954c4f9b48f49be51eca55f630f9a7311e28dc5c237f090fa4ebc0c9
|
|
| MD5 |
40d166382530b0d9bfbf06fd192b1fb4
|
|
| BLAKE2b-256 |
d5eaef909e51028f675d170ddc51d288fd7253afdb2293b9c4ae1884cb6d9533
|
Provenance
The following attestation bundles were made for malaysian_address_parser-0.1.1-py3-none-any.whl:
Publisher:
release.yml on imad210/MALAYSIAN_ADDRESS_PARSER
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
malaysian_address_parser-0.1.1-py3-none-any.whl -
Subject digest:
9bf21268954c4f9b48f49be51eca55f630f9a7311e28dc5c237f090fa4ebc0c9 - Sigstore transparency entry: 1018778350
- Sigstore integration time:
-
Permalink:
imad210/MALAYSIAN_ADDRESS_PARSER@2c9c364b21e2defaca7f6f7a5cb9528d7e3a1300 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/imad210
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2c9c364b21e2defaca7f6f7a5cb9528d7e3a1300 -
Trigger Event:
push
-
Statement type: