Ngiêm cấm sử đụng PROXY và VPS vào mục đích trái pháp luật bạn sẽ phải chịu toàn bộ trách nhiệm trước pháp luật khi sử dụng dịch vụ của chúng tôi tks!
OpenStreetMap Nominatim geocoding: chính sách và cache

OpenStreetMap Nominatim geocoding: chính sách, cache và ứng viên

Chuyên viên Kỹ thuật ProxyVN 04-26-2026 Đang tính... phút đọc

OpenStreetMap Nominatim geocoding là cách đổi một địa chỉ thành tọa độ bằng dữ liệu OSM, có chính sách dùng rất rõ cho máy chủ công cộng. Bài này viết cho người có danh sách địa chỉ cần đổi mà vẫn đúng luật chơi. ProxyVN ghi trung thực: máy lab không vào được máy chủ công cộng, nên client thật chạy trên máy chủ mô phỏng dùng dữ liệu OSM thật.

OpenStreetMap Nominatim geocoding: mục tiêu và phạm vi không lặp

Phần này chốt bài toán, đầu ra và giới hạn lab, vì giới hạn này ảnh hưởng tới cách anh em đọc mọi con số phía sau.

Bài toán cần giải

Một nhóm vận hành có vài trăm địa chỉ cửa hàng và muốn đặt lên bản đồ. Họ viết vòng lặp gọi API, chạy bốn luồng cho nhanh, và không lưu lại kết quả. Vài hôm sau script báo lỗi, vì mỗi lần chạy lại đều gửi nguyên danh sách. Số khác lại bị đặt sai tỉnh, vì kết quả đầu tiên không phải địa chỉ họ muốn.

Đầu ra nghiệm thu

Đầu ra là bảng gồm query gốc, query chuẩn hóa, osm_type, osm_id, tọa độ, bounding box, mức chi tiết kết quả và trạng thái duyệt. Đi kèm là cache truy vấn theo chính sách hiện hành. Mỗi dòng phải cho biết kết quả được máy chọn hay người đã xác nhận.

Ranh giới với bài Overpass

Bài Overpass API bằng Python truy vấn đối tượng OSM theo vùng và thẻ, ví dụ mọi trạm xăng trong một quận. Bài này đi chiều khác: từ một chuỗi địa chỉ ra một đối tượng. Muốn tải toàn bộ điểm trong một vùng thì không dùng Nominatim, chính sách cấm việc đó và Overpass hay bản trích OSM mới là công cụ đúng.

Giới hạn của lab cần nói ngay

Trên máy lab, DNS trả 127.0.0.1 cho nominatim.openstreetmap.org và www.openstreetmap.org, nên kết nối thất bại. Lab không tìm cách vòng qua việc này. Thay vào đó, lab lấy dữ liệu OSM thật qua Photon của Komoot, một bộ geocoder khác cũng dựng trên OSM. Sau đó lab dựng máy chủ cục bộ trả JSON đúng dạng tài liệu Nominatim.

Điều đó có nghĩa gì với anh em

Các osm_id, tên, tọa độ và hộp bao trong bài là dữ liệu OSM thật. Thứ tự xếp hạng là của Photon, không phải của Nominatim, nên kết quả thật có thể khác. Trường place_id và importance trong máy chủ lab do lab đặt. Phần giới hạn nhịp, cache và luồng duyệt chạy thật bằng client thật.

Ai nên đọc

Bài hợp với người vận hành cần đặt vài trăm điểm lên bản đồ, kỹ sư dữ liệu làm sạch địa chỉ, người dựng ứng dụng có ô tìm địa điểm. Người cần geocoding liên tục cho sản phẩm chính nên đọc kỹ phần tự vận hành, vì máy chủ công cộng không dành cho nhu cầu đó.

Những gì bài không làm

Bài không so sánh chất lượng giữa các nhà cung cấp geocoding. Bài không hướng dẫn cài đặt Nominatim từ đầu. Bài cũng không đề cập reverse geocoding, tức từ tọa độ ra địa chỉ, ngoài vài dòng về chính sách.

Thuật ngữ dùng trong bài

Geocoding là đổi địa chỉ thành tọa độ. Instance là một máy chủ Nominatim cụ thể. OSM object là một node, way hoặc relation trong OpenStreetMap. Bounding box là hộp bao gồm bốn cạnh. Candidate là một kết quả ứng viên cho query.

Geocode địa chỉ bằng instance được phép và phân biệt usage policy với OpenStreetMap Nominatim geocoding

Phần này đọc chính sách trước khi viết dòng code nào, vì sai ở đây thì code đúng cũng vô nghĩa.

Nguồn tài liệu đã đọc

Lab đọc chính sách sử dụng Nominatim của OSM Foundation, tài liệu endpoint Search và tài liệu định dạng Output. Ba trang này mở được từ máy lab vì nằm trên tên miền khác. Mọi điều bài nói về chính sách đều đọc từ trang đầu, ngày 05/11/2026.

Các yêu cầu cứng của máy chủ công cộng

Chính sách áp cho máy chủ do OSM Foundation vận hành. Anh em cần nhớ những điểm sau trước khi gửi request đầu tiên.

  • Nhịp gọi: mức trần chính sách ghi là một request mỗi giây, tính trên toàn ứng dụng.
  • Danh tính: phải có Referer hoặc User-Agent nhận diện ứng dụng, User-Agent mặc định của thư viện không được chấp nhận.
  • Ghi công: hiển thị attribution rõ ràng, dữ liệu theo giấy phép ODbL.
  • Cache: với tác vụ hàng loạt, kết quả phải được lưu ở phía anh em.
  • Đổi dịch vụ: ứng dụng phải chuyển được sang nơi khác mà không cần cập nhật phần mềm.

Bulk geocoding bị hạn chế ra sao

Chính sách không khuyến khích geocoding hàng loạt. Việc một lần, quy mô nhỏ có thể chấp nhận nếu chạy một luồng, trên một máy, không phân tán. Script chạy quá một ngày hoặc chạy định kỳ bị giới hạn bốn request mỗi phút. Client gửi lặp cùng một query có thể bị xếp loại lỗi và bị chặn.

Những việc bị cấm hẳn

Chính sách liệt kê các việc sẽ bị cấm truy cập. Đó là tự làm ô gợi ý khi gõ, truy vấn có hệ thống như quét lưới, tải tự động trang details và bán lại kết quả. Dịch vụ mà geocoding là chức năng chính phải tự chạy máy chủ riêng. Ô tìm kiếm trong ứng dụng chỉ nên gọi khi người dùng bấm tìm.

Phần chính sách dành cho code do AI sinh

Chính sách có một mục riêng về mô hình ngôn ngữ, và ghi rằng code do AI sinh cũng phải tuân thủ mọi điều khoản. ProxyVN nhắc rõ ở đây: mọi đoạn code dưới đây phải chạy theo chính sách đó, anh em đọc bản gốc trước khi dùng. Chính sách cũng cấm nhúng API công cộng vào các nền tảng no-code như một dịch vụ geocoding chung. Người phát triển phải tự quyết định có ý thức và tự chịu trách nhiệm tuân thủ.

Chọn instance nào

Bảng: Chọn instance nào

Nhu cầu

Lựa chọn hợp

Lý do

Vài trăm địa chỉ, một lần

Máy chủ công cộng, một luồng

Chính sách cho phép việc nhỏ

Chạy định kỳ hằng ngày

Tự vận hành hoặc nhà cung cấp

Giới hạn 4 request mỗi phút

Ô tìm kiếm trong app đông người

Nhà cung cấp hoặc tự vận hành

Tổng lưu lượng tính theo app

Gợi ý khi gõ

Dịch vụ hỗ trợ autocomplete

Bị cấm ở máy chủ công cộng

Mọi điểm trong vùng

Bản trích OSM hoặc Overpass

Quét có hệ thống bị cấm

Cấu hình để đổi instance

Vì chính sách đòi đổi được dịch vụ, base URL phải nằm trong cấu hình, không viết chết trong code. Trong lab, chỉ cần đổi base từ máy chủ lab sang instance thật là chạy lại được. Đây cũng là lý do bài dùng được dù lab không chạm máy chủ công cộng.

import os
 
BASE = os.environ.get("NOMINATIM_BASE", "https://nominatim.openstreetmap.org/search")
UA = {"User-Agent": "TenUngDung/1.0 (+https://example.com/lien-he)"}

Anh em thay tên ứng dụng và đường liên hệ bằng của dự án thật. Tài liệu còn có tham số email cho người gửi nhiều request, dùng địa chỉ của dự án.

Chọn Nominatim instance và đọc usage policy cho OpenStreetMap Nominatim geocoding

Phần này biến chính sách thành một lớp client, để nhịp gọi không phụ thuộc vào trí nhớ của người chạy script.

Thử User-Agent mặc định

Máy chủ lab được viết để từ chối chuỗi python-requests, mô phỏng đúng yêu cầu của chính sách. Lời gọi không đặt header nhận HTTP 403 từ máy chủ lab. Mã trả về của máy chủ thật có thể khác, lab không kiểm được. Điểm cần nhớ là đặt User-Agent riêng ngay từ đầu.

Lớp client có giới hạn nhịp

Lớp G dưới đây giữ khoảng cách 1.1 giây giữa hai request mạng, và chỉ gọi mạng khi cache không có. Khoảng 1.1 giây là tự chọn để có biên an toàn dưới mức một giây. Với script chạy định kỳ, anh em đổi gap thành 15 giây để khớp bốn request mỗi phút.

import hashlib, json, re, sqlite3, time, unicodedata, requests
 
db = sqlite3.connect("geocache.sqlite")
db.execute("create table if not exists c(k text primary key, q text, params text, fetched real, body text)")
 
def norm(q):
    return re.sub(r"\s+", " ", unicodedata.normalize("NFC", q)).strip().lower()
 
class G:
    def __init__(self, base, gap=1.1):
        self.base, self.gap, self.last, self.net, self.hit = base, gap, 0, 0, 0
 
    def search(self, q, **p):
        p = dict(format="jsonv2", limit=5, addressdetails=1, **p)
        k = hashlib.sha256((norm(q) + json.dumps(p, sort_keys=True)).encode()).hexdigest()
        row = db.execute("select body from c where k=?", (k,)).fetchone()
        if row:
            self.hit += 1
            return json.loads(row[0])
        w = self.gap - (time.time() - self.last)
        if w > 0:
            time.sleep(w)
        r = requests.get(self.base, params=dict(p, q=q), headers=UA, timeout=20)
        self.last = time.time()
        r.raise_for_status()
        self.net += 1
        db.execute("insert into c values(?,?,?,?,?)", (k, q, json.dumps(p), time.time(), r.text))
        db.commit()
        return r.json()

Khóa cache gồm query đã chuẩn hóa và bộ tham số. Đổi tham số countrycodes thì là truy vấn khác, nên không dùng lại kết quả cũ.

Kết quả chạy lab

Lab gửi 11 query qua lớp G, trong đó có ba bản lặp của "Hoàn Kiếm, Hà Nội": bản gốc, bản thừa khoảng trắng và viết thường, bản Unicode dạng NFD. Client gọi mạng 8 lần, trúng cache 3 lần, mất 7.9 giây. Máy chủ lab ghi 8 request và 0 lần hai request cách nhau dưới một giây.

Chạy bốn luồng thì sao

Lab cho bốn luồng gửi thẳng 8 query, không qua lớp G. Máy chủ lab ghi 8 trên 8 request vi phạm khoảng một giây. Đây là kiểu script ở đầu bài, tuy chạy nhanh nhưng trái chính sách. Giới hạn nhịp phải nằm ở một chỗ cho toàn ứng dụng, không phải trong từng luồng.

Chuẩn hóa Unicode là vì tiếng Việt

Chuỗi tiếng Việt có hai dạng biểu diễn. Dữ liệu copy từ một số hệ thống ra dạng tổ hợp NFD, nhìn giống hệt nhưng khác byte. Không chuẩn hóa thì cache coi là hai query, và máy chủ nhận lặp. Lab xác nhận bản NFD trúng cache sau khi chuẩn hóa về NFC.

Không bỏ dấu để gom cache

Query "Hoan Kiem Ha Noi" không dấu trong lab là một khóa riêng. Lab không tự bỏ dấu khi gom, vì nhiều địa danh Việt Nam chỉ khác nhau ở dấu. Bỏ dấu có thể gộp nhầm hai nơi khác nhau. Một lượt gọi thêm rẻ hơn một kết quả sai.

Khi nào cache hết hạn

Chính sách yêu cầu cache nhưng không ghi thời hạn trên trang lab đọc. Dữ liệu OSM thay đổi liên tục, nhưng địa chỉ ít khi đổi trong vài tuần. Lab lưu thời điểm tải để dự án tự đặt hạn, ví dụ vài tháng. Thời hạn này là quy ước dự án, nên ghi vào tài liệu.

Gọi search địa chỉ với tham số format, address cần thiết trong OpenStreetMap Nominatim geocoding

Tham số đúng giúp giảm kết quả sai trước khi cần tới người duyệt.

Các tham số lab dùng

Tham số thu hẹp kết quả

Tham số thu hẹp kết quả

Lab dùng format=jsonv2, limit=5, addressdetails=1. Tài liệu ghi limit mặc định 10, tối đa 40, và Nominatim có thể trả ít hơn khi kết quả khác không khớp đủ. Jsonv2 đổi class thành category và thêm place_rank. Addressdetails trả khối địa chỉ tách theo cấp, rất hữu ích cho bước kiểm.

Giới hạn theo quốc gia

Tham số countrycodes nhận mã ISO hai chữ, ví dụ vn. Với danh sách địa chỉ trong nước, nên luôn truyền. Query "Lê Lợi" không giới hạn có thể ra đường ở nơi khác trên thế giới. Tài liệu cũng có viewbox làm tăng ưu tiên một vùng, và bounded=1 biến nó thành bộ lọc cứng.

Dùng viewbox cho từng tỉnh

Khi biết địa chỉ thuộc tỉnh nào, anh em truyền viewbox bằng hộp bao của tỉnh. Viewbox nhận x1,y1,x2,y2 với x là kinh độ, y là vĩ độ. Thứ tự này khác thứ tự boundingbox trong response. Trộn hai thứ tự là lỗi hay gặp.

Truy vấn có cấu trúc

Tài liệu có dạng structured query với các trường street, city, county, state, country, postalcode. Dữ liệu đã tách cột thì dạng này giảm mơ hồ so với một chuỗi tự do. Tài liệu ghi hai dạng không dùng chung trong một request. Lab chưa chạy dạng này vì máy chủ mô phỏng chỉ dựng q.

params = dict(
    street="1 Đại Cồ Việt", city="Hà Nội", country="Việt Nam",
    format="jsonv2", addressdetails=1, limit=5,
)

Đây là ví dụ triển khai theo tài liệu, chưa chạy trên máy chủ thật. Anh em thử trên vài dòng trước khi chạy cả danh sách.

Ngôn ngữ kết quả

Tham số accept-language chọn ngôn ngữ của tên trả về, mặc định theo header Accept-Language. Bảng cho người Việt nên đặt vi. Nếu không đặt, kết quả có thể đổi theo môi trường chạy script, làm cache khó giải thích.

Lọc theo layer

Tham số layer giới hạn theo nhóm như address, poi, railway, natural, manmade. Với địa chỉ cửa hàng, layer=address loại bớt trạm xe buýt hay hồ nước trùng tên. Lab thấy "Hoàn Kiếm, Hà Nội" có cả hồ và quận trong năm ứng viên, nên lọc theo nhu cầu rất có ích.

Bảng query và ứng viên trong lab

Bảng dưới là dữ liệu OSM thật lấy qua Photon, ba ứng viên đầu của mỗi query, không phải thứ tự của Nominatim.

Bảng: Bảng query và ứng viên trong lab

Query

Ứng viên 1

Ứng viên 2

Ứng viên 3

Hoàn Kiếm, Hà Nội

relation 9421131, Quận Hoàn Kiếm

relation 198437, Hồ Hoàn Kiếm

relation 19331651, suburb

Chợ Bến Thành

way 39514795, marketplace

node 3166133536, bus_stop

way 1258471548, shop ở Nha Trang

Đà Nẵng

relation 1891418, city

node 10553910677, station

way 316236720, hotel

Lê Lợi, Huế

way 695775622, school

way 438257497, hospital

way 1236597213, đường ở Sơn Trung

Đọc bảng này

"Chợ Bến Thành" có ứng viên thứ ba là cửa hàng tiện lợi cùng tên tại Nha Trang. "Lê Lợi, Huế" đưa trường và bệnh viện lên trước, còn đường Lê Lợi trong ba ứng viên lại ở nơi khác. Một địa chỉ thiếu số nhà và thiếu loại đối tượng dễ ra đối tượng đúng tên nhưng sai bản chất.

Query không có kết quả

Chuỗi "địa chỉ không tồn tại xyz" trả mảng rỗng. Lớp G lưu cả kết quả rỗng vào cache. Nếu không, script sẽ lặp lại query thất bại ở mọi lần chạy, đúng hành vi chính sách cảnh báo. Dòng rỗng xếp vào nhóm cần sửa chuỗi địa chỉ.

Giữ place ID, bounding box và mức chi tiết kết quả của OpenStreetMap Nominatim geocoding

Tên đề mục dùng chữ place ID vì đó là thứ nhiều người muốn lưu, nhưng tài liệu khuyên điều khác.

place_id không phải khóa bền

OSM ID bền hơn place_id

OSM ID bền hơn place_id

Tài liệu Output có mục riêng ghi place_id không phải id bền vững. Giá trị này gắn với một instance và có thể đổi khi dữ liệu được nhập lại. Không dùng place_id làm khóa trong bảng lâu dài, cũng không dùng để ghép giữa hai instance. Lab vẫn lưu nó như thông tin phụ của lần gọi.

Khóa nên lưu

Khóa ổn định hơn là cặp osm_type và osm_id, ví dụ relation 9421131. Tài liệu Output có mục tham chiếu OSM cho việc này. Dù vậy đối tượng OSM cũng có thể bị xóa hoặc tách, nên bảng cần ngày tải. Node 123 và way 123 là hai đối tượng khác nhau, vì vậy luôn giữ cả loại.

Thứ tự của boundingbox

Tài liệu ví dụ boundingbox là mảng bốn chuỗi: vĩ độ nam, vĩ độ bắc, kinh độ tây, kinh độ đông. Ví dụ Quận Hoàn Kiếm trong lab là 21.0181302, 21.04321, 105.8409287, 105.8672823. Nhiều thư viện bản đồ dùng thứ tự khác, thường là tây, nam, đông, bắc. Đổi thứ tự sai thì hộp bao nằm giữa đại dương.

Mọi tọa độ đều là chuỗi

Lat, lon và các phần tử boundingbox trả dạng chuỗi trong ví dụ tài liệu. Script phải đổi sang số trước khi tính, và giữ chuỗi gốc trong lớp thô. So sánh chuỗi có thể cho kết quả sai với số âm hoặc khác số chữ số. Bước đổi nên nằm ở một hàm duy nhất.

def bbox(res):
    s, n, w, e = map(float, res["boundingbox"])
    return {"south": s, "north": n, "west": w, "east": e,
            "height_deg": round(n - s, 4), "width_deg": round(e - w, 4)}
 
def size_class(b):
    d = max(b["height_deg"], b["width_deg"])
    if d == 0:
        return "diem"
    if d < 0.01:
        return "cong_trinh_hoac_pho"
    if d < 0.2:
        return "quan_huyen"
    return "tinh_thanh_tro_len"

Các ngưỡng trong size_class do lab tự đặt để minh họa, không phải quy ước của Nominatim. Mục đích là phát hiện địa chỉ cửa hàng mà kết quả lại là cả một thành phố.

Hộp bao nói lên mức chi tiết

Với query "Đà Nẵng", hộp bao của relation 1891418 rộng từ 14.95 tới 16.33 độ vĩ, và từ 107.21 tới 109.02 độ kinh. Hộp này lớn hơn nhiều so với trung tâm thành phố. Một tọa độ duy nhất của kết quả đó không có nghĩa là địa chỉ chính xác. Bảng nên giữ size_class để không vẽ một ghim tại tâm rồi gọi đó là cửa hàng.

Node không có hộp bao riêng

Trong dữ liệu Photon, node không có extent, nên máy chủ lab trả hộp bao có bốn cạnh trùng điểm. Tài liệu Nominatim trả boundingbox cho kết quả, và trạm xe buýt trong lab cho hộp bao rộng 0. Hàm size_class xử lý trường hợp này bằng nhãn diem. Khi chạy thật, anh em kiểm lại cách máy chủ trả với node.

Trường category và type

Category và type là khóa, giá trị thẻ OSM chính. Hồ Hoàn Kiếm là water, lake. Quận Hoàn Kiếm là boundary, historic trong dữ liệu Photon, nhắc rằng ranh giới hành chính có thể đã đổi. Với địa chỉ cửa hàng, category boundary hoặc place cho thấy kết quả chỉ tới cấp vùng.

Place_rank giúp gì

Jsonv2 có place_rank, cho biết cấp tìm kiếm của đối tượng. Giá trị này trong máy chủ lab là 0 vì Photon không có. Khi chạy thật, trường này cùng addressdetails là căn cứ tốt hơn để biết kết quả tới cấp nhà, cấp đường hay cấp quận. Lab chưa kiểm được phần này.

Địa danh sau sáp nhập

Việt Nam có thay đổi đơn vị hành chính, và dữ liệu OSM cập nhật theo đóng góp cộng đồng. Một địa chỉ ghi quận cũ có thể khớp ranh giới lịch sử hoặc không khớp gì. Anh em giữ nguyên địa chỉ gốc trong bảng, thêm cột đã chuẩn hóa nếu có. Đừng ghi đè chuỗi gốc.

Cache query và xử lý địa chỉ nhiều ứng viên có ghi confidence thủ công trong OpenStreetMap Nominatim geocoding

Phần này biến danh sách ứng viên thành quyết định có người chịu trách nhiệm.

Luật chọn đơn giản

Duyệt nhiều ứng viên

Duyệt nhiều ứng viên

Lab chia kết quả làm ba nhóm. Mảng rỗng là khong_co. Một ứng viên là mot_ung_vien. Từ hai ứng viên trở lên là can_duyet. Trong 8 query của lab, 6 thuộc nhóm cần duyệt, 1 có một ứng viên, 1 không có kết quả.

def decide(a):
    if not a:
        return "khong_co"
    if len(a) == 1:
        return "mot_ung_vien"
    return "can_duyet"

Hàm rất ngắn, và phần giá trị nằm ở bảng duyệt phía sau chứ không ở hàm.

Một ứng viên chưa chắc đúng

Query "Nguyễn Trãi" chỉ có một kết quả trong dữ liệu Photon, là một đoạn quốc lộ ở Thanh Hóa. Anh em nào đang tìm đường Nguyễn Trãi ở Hà Nội sẽ nhận kết quả sai mà không có cảnh báo. Nhóm mot_ung_vien vẫn cần kiểm tỉnh trong addressdetails. Một kết quả không có nghĩa là một kết quả đúng.

Đừng dùng importance làm độ tin cậy

Importance là độ quan trọng tính toán của đối tượng, không phải độ khớp với query. Một thành phố lớn có importance cao dù địa chỉ anh em tìm là một con hẻm. Nominatim không trả một trường confidence cho kết quả. Vì vậy brief của bài dùng cụm "confidence thủ công": cột này do người hoặc luật của dự án ghi.

Thang confidence của dự án

Lab đề xuất ba mức để dễ dùng. Mức A là người đã xem trên bản đồ. Mức B là luật tự động khớp đủ tỉnh, quận và loại đối tượng. Mức C là chưa kiểm. Thang này là đề xuất của bài, dự án có thể đổi.

Bảng: Thang confidence của dự án

Mức

Điều kiện

Có dùng vào báo cáo

A

Người xác nhận trên bản đồ

Có

B

Khớp tỉnh, quận, loại đối tượng theo luật

Có, kèm ghi chú

C

Chưa kiểm hoặc nhiều ứng viên

Không

Luật kiểm tỉnh

Khi địa chỉ gốc có cột tỉnh, luật đơn giản so khối addressdetails với cột đó. Khác tỉnh thì loại ứng viên. Với dữ liệu thật, trường address có các khóa như city, state và ISO3166-2-lvl4 theo ví dụ tài liệu. Lab chưa chạy luật này vì Photon không trả cùng khối địa chỉ.

Giao diện duyệt tối giản

Một bảng tính là đủ cho vài trăm dòng. Mỗi dòng có địa chỉ gốc, các ứng viên và liên kết mở bản đồ. Người duyệt chọn osm_type, osm_id đúng, script ghi vào cột cuối cùng. Lựa chọn của người được lưu riêng để không mất khi chạy lại.

Cache kết quả rỗng và lỗi

Kết quả rỗng được cache, còn lỗi mạng hay 5xx thì không. Nếu cache lỗi, script sẽ tin rằng địa chỉ không có kết quả. Lớp G gọi raise_for_status trước khi ghi nên đã xử lý đúng điều này.

Dữ liệu và quyền riêng tư

Địa chỉ cá nhân gửi lên dịch vụ bên ngoài là dữ liệu nhạy cảm. Chính sách của OSM có phần về quyền riêng tư theo chính sách chung của Foundation. Với địa chỉ khách hàng, dự án nên cân nhắc tự vận hành. Cache cục bộ cũng phải được bảo vệ như dữ liệu gốc.

Tự vận hành và vai trò proxy với OpenStreetMap Nominatim geocoding

Phần này giải thích một chữ proxy dễ hiểu sai trong chính sách, và chỉ đường khi nhu cầu vượt mức máy chủ công cộng.

Chữ proxy trong chính sách nghĩa là gì

Chính sách khuyên nếu có thể thì dựng proxy và bật cache cho request. Ở đây proxy là một lớp trung gian của chính ứng dụng, gom và cache truy vấn trước khi gửi lên Nominatim, và là nơi đổi instance được mà không cập nhật app. Nó không có nghĩa là xoay IP để gửi nhiều hơn. Chính sách nói rõ giới hạn tính trên toàn ứng dụng và cấm script phân tán.

Không đổi IP để vượt chính sách

Dùng nhiều IP để tránh giới hạn một request mỗi giây là đúng thứ chính sách cấm, vì đó là script phân tán. ProxyVN không khuyên cách đó. Nếu nhu cầu lớn, các lối đi đúng là chạy instance riêng hoặc dùng nhà cung cấp thương mại. Cách đặt nhịp hợp lý có ở bài rate limit API khi dùng proxy.

Tự vận hành khi nào hợp lý

Nominatim là phần mềm mở, có tài liệu cài đặt riêng. Bản trích dữ liệu Việt Nam nhỏ hơn nhiều so với toàn cầu. Khi đó giới hạn do chính anh em đặt, và địa chỉ khách hàng không rời hạ tầng. Lab chưa cài đặt nên bài không đưa cấu hình phần cứng. Chi phí vận hành cần được tính thật trước khi quyết định.

Proxy doanh nghiệp ở tầng tải

Khi mạng công ty buộc đi qua cổng ra, anh em đặt ở session của lớp G, chuỗi theo định dạng proxy. Một cổng ra cố định không vi phạm gì. Phần cache và duyệt chạy offline. Bài Web Scraping proxy là gì phân biệt các vai trò này.

Tác vụ thu thập khác cần IP ổn định thì anh em có thể mua proxy uy tín tại trang chủ ProxyVN.

Ghi công trên bản đồ

Bản đồ hay bảng công bố phải có ghi công OpenStreetMap rõ ràng. Trường licence trong response nhắc dữ liệu thuộc OpenStreetMap contributors, ODbL 1.0. Bảng xuất ra nên giữ dòng này. Ghi công đặt ở nơi người dùng nhìn thấy, không chôn trong trang điều khoản.

Khóa phiên bản

Lab chạy Python 3.12.10, requests 2.34.2, tài liệu Nominatim bản 5.3.3 theo tiêu đề trong brief. Các tham số như layer phụ thuộc phiên bản máy chủ. Với instance khác, gọi endpoint status trước để biết phiên bản.

Đầu ra nghiệm thu bảng query, OSM ID, bounding box và cache của OpenStreetMap Nominatim geocoding

Mục này chốt bảng cuối và danh sách kiểm trước khi đưa dữ liệu lên bản đồ.

Schema của bảng

Nghiệm thu và chính sách

Nghiệm thu và chính sách

Bảng: Schema của bảng

Cột

Ví dụ từ lab

Ghi chú

query_raw

Chợ Bến Thành

Không sửa

query_norm

chợ bến thành

Khóa cache

osm_type

way

Luôn đi cùng id

osm_id

39514795

Khóa ổn định hơn place_id

lat, lon

10.7725301, 106.6980365

Đổi từ chuỗi

bbox

10.7718338, 10.7733076, 106.6973374, 106.6986973

Nam, bắc, tây, đông

size_class

cong_trinh_hoac_pho

Quy ước dự án

decision

can_duyet

khong_co, mot_ung_vien, can_duyet

confidence

A

Do người hoặc luật ghi

fetched_at

2026-11-05

Tính hạn cache

Danh sách kiểm chính sách

  • Nhịp: có một chỗ duy nhất giữ khoảng cách request, một luồng.
  • Danh tính: User-Agent nhận diện ứng dụng, có đường liên hệ.
  • Cache: query lặp không gửi lại, kể cả kết quả rỗng.
  • Cấu hình: base URL đổi được không cần sửa code.
  • Ghi công: có attribution OSM và ODbL ở bản công bố.
  • Phạm vi: không autocomplete, không quét có hệ thống, không bán lại.

Câu kết luận được phép viết

Từ lab có thể viết rằng lớp client giữ nhịp và cache làm giảm request lặp. Bốn luồng không giới hạn vi phạm nhịp ở mọi request trên máy chủ lab. Chuẩn hóa NFC gom được chuỗi tiếng Việt khác byte. Không nên viết gì về chất lượng xếp hạng của Nominatim, vì lab chưa nhận được kết quả thật.

Những gì lab chưa chạy

Lab chưa gửi request nào tới máy chủ Nominatim thật. Lab chưa thử structured query, viewbox, layer, addressdetails thật và status thật. Mã trả về khi vi phạm chính sách là chưa rõ. Anh em có mạng vào được nên chạy lại đoạn lớp G với vài dòng, giữ đúng nhịp, rồi đối chiếu cấu trúc.

Việc nên làm trên mạng khác

Đổi biến NOMINATIM_BASE sang máy chủ công cộng. Gửi đúng 8 query trong bài, một luồng. So osm_id và thứ tự với bảng của lab. Kết quả so sánh đó mới là thứ đủ để viết về xếp hạng.

Một luồng, một chỗ giữ nhịp, cache mọi query, và lưu osm_id thay cho place_id. Chính sách là phần đầu tiên của code, không phải phần phụ lục.

OpenStreetMap Nominatim geocoding: câu hỏi thường gặp

Các câu dưới đây gom những điểm hay bị hỏi.

Có cần khóa API không?

Máy chủ công cộng không cần khóa, nhưng phải có User-Agent hoặc Referer nhận diện ứng dụng và tuân thủ chính sách.

Một giây một request áp cho ai?

Áp trên toàn ứng dụng. Tổng lưu lượng của mọi người dùng không được vượt mức đó.

Có làm ô gợi ý khi gõ được không?

Không. Chính sách cấm autocomplete phía client trên máy chủ công cộng.

Nên lưu place_id không?

Có thể lưu để tham khảo, nhưng tài liệu ghi nó không bền. Khóa nên dùng cặp osm_type và osm_id.

Script chạy mỗi ngày có được không?

Chính sách giới hạn script định kỳ ở bốn request mỗi phút, và cần cache kết quả. Nhu cầu đều đặn nên chuyển sang instance riêng.

Nominatim có trả độ tin cậy không?

Không có trường confidence. Importance là độ quan trọng của đối tượng, không phải độ khớp.

Proxy có giúp gửi nhanh hơn không?

Không nên dùng theo cách đó. Chính sách cấm script phân tán, và giới hạn tính theo ứng dụng.

Máy tôi không vào được máy chủ công cộng thì sao?

Kiểm DNS và mạng nội bộ trước. Nếu mạng chặn, hỏi người quản trị mạng thay vì tự vòng qua, hoặc dùng instance được phép trong tổ chức.

OpenStreetMap Nominatim geocoding và những điều cần nhớ

OpenStreetMap Nominatim geocoding chạy tốt khi anh em đọc chính sách trước, giữ một luồng, cache mọi query, lưu osm_id thay cho place_id và để người duyệt ứng viên mơ hồ. Nhu cầu lớn thì tự vận hành. Proxy.vn - Nhà cung cấp dịch vụ proxy chất lượng hàng đầu Việt Nam khuyên anh em giữ đúng nhịp khi dùng OpenStreetMap Nominatim geocoding.

TIN TỨC LIÊN QUAN