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!
Open-Meteo archive API: lịch sử thời tiết theo lưới

Open-Meteo archive API: lịch sử thời tiết theo lưới và múi giờ

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

Open-Meteo archive API là cách lấy lịch sử thời tiết theo tọa độ từ dữ liệu mô hình, không cần khóa. Bài này viết cho người dựng bảng theo giờ cần ghi đúng model, múi giờ và đơn vị. ProxyVN đã gọi API thật ngày 05/11/2026 cho Hà Nội và Berlin, thấy tọa độ bị dời về ô lưới, và thấy timestamp dùng một độ lệch cố định qua cả năm.

Open-Meteo archive API: mục tiêu và phạm vi không lặp

Phần này chốt bài toán và ranh giới để anh em không dùng nhầm loại dữ liệu.

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

Một nhóm phân tích bán hàng muốn ghép doanh số theo giờ với nhiệt độ và lượng mưa tại Hà Nội. Họ cần lịch sử vài năm, nên gọi API theo khoảng ngày rồi ghép vào bảng đơn hàng. Bảng chạy được, nhưng cột giờ lệch bảy tiếng vì quên tham số timezone. Một người khác lại ghi nguồn là "trạm Hà Nội", trong khi số liệu đến từ một ô lưới của mô hình.

Đầu ra nghiệm thu

Đầu ra là bảng giờ gồm thời điểm UTC, thời điểm địa phương, biến, giá trị, đơn vị. Đi kèm là phần ghi nguồn gồm model, tọa độ yêu cầu, tọa độ ô lưới, độ cao và ngày truy vấn. Bảng này phải trả lời được câu hỏi "số này từ đâu" mà không cần chạy lại.

Ranh giới với dữ liệu trạm

Bài NOAA trong cụm này nói về quan trắc tại trạm, có cờ chất lượng và ngày thiếu. Open-Meteo archive trả dữ liệu tái phân tích và mô hình trên lưới, nên không có khái niệm trạm thiếu số. Không có khoảng trống không có nghĩa là số đã được đo tại chỗ. Hai nguồn này trả lời hai câu hỏi khác nhau.

Giới hạn của lab

Lab gọi khoảng 20 lượt tới archive-api.open-meteo.com, không khóa, nghỉ hai giây giữa các lượt. Lab chỉ đọc nhiệt độ, mưa và gió trong vài ngày mẫu. Lab không so với trạm thật nào, nên bài không đưa con số về sai số của mô hình.

Ai nên đọc

Bài hợp với người làm phân tích bán hàng, logistics, nông nghiệp hoặc nội dung thời tiết cần lịch sử theo giờ. Kỹ sư dữ liệu nên đọc kỹ phần múi giờ. Người cần số đo pháp lý cho bảo hiểm hay tranh chấp nên dùng trạm khí tượng chính thức, không dùng bài này.

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

Bài không dự báo thời tiết. Bài không giải thích cách mô hình tái phân tích được tính. Bài cũng không dùng API dự báo hay API single runs, dù hai dịch vụ đó có trên cùng trang tài liệu.

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

Reanalysis là dữ liệu dựng lại quá khứ bằng cách kết hợp quan trắc với mô hình. Grid là lưới ô của mô hình. Model trong tham số models là bộ dữ liệu được chọn. Offset là độ lệch giây so với UTC mà API trả trong utc_offset_seconds. Cả bốn từ này sẽ quay lại nhiều lần ở các phần sau.

Lấy lịch sử thời tiết theo tọa độ với timezone và unit rõ bằng Open-Meteo archive API

Phần này đi qua lời gọi đầu tiên và các trường mà response trả về.

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

Lab đọc trang Historical Weather API của Open-Meteo cho tham số, bộ dữ liệu và độ trễ. Phần giới hạn và giấy phép lấy từ điều khoản Open-Meteo. Hai trang này trả HTTP 200 ngày lab chạy, và lab đối chiếu chúng với response thật.

Lời gọi đầu tiên

Endpoint là https://archive-api.open-meteo.com/v1/archive. Tham số bắt buộc gồm latitude, longitude, start_date, end_date. Lab xin ba biến hourly cho hai ngày đầu tháng 10/2026 tại tọa độ trung tâm Hà Nội.

import requests
 
B = "https://archive-api.open-meteo.com/v1/archive"
p = dict(
    latitude=21.0285, longitude=105.8542,
    start_date="2026-10-01", end_date="2026-10-02",
    hourly="temperature_2m,precipitation,wind_speed_10m",
)
a = requests.get(B, params=p, timeout=60).json()
print({k: a[k] for k in a if k != "hourly"})
print(a["hourly"]["time"][:2], a["hourly"]["temperature_2m"][:2], len(a["hourly"]["time"]))

Response có latitude 21.05448, longitude 105.898476, elevation 19.0, timezone GMT, utc_offset_seconds 0. Khối hourly_units ghi time là iso8601, nhiệt độ °C, mưa mm, gió km/h. Khối hourly có 48 mốc giờ cho hai ngày.

Tọa độ trả về khác tọa độ gửi

Lab gửi 21.0285, 105.8542 nhưng nhận 21.05448, 105.898476. Đó là tâm ô lưới được chọn, cách điểm gửi khoảng 5 km theo phép tính của lab. Tại Quảng Ninh, lab gửi 20.9, 107.1 và nhận 20.843584, 107.03441, cách khoảng 9 km. Luôn lưu cả tọa độ gửi và tọa độ trả về, vì người đọc sẽ hỏi số này đại diện cho điểm nào.

Độ cao trong response

Elevation trả 19.0 cho Hà Nội và 7.0 cho điểm Quảng Ninh. Lab thử truyền elevation=10 cho Hà Nội, response ghi lại 10.0 nhưng ba giá trị nhiệt độ đầu vẫn là 27.8, 27.9, 27.5 như khi không truyền. Lab chỉ thử một ô nên không kết luận về cơ chế hiệu chỉnh. Nếu dự án dùng tham số này, anh em nên ghi lại giá trị đã truyền.

Không truyền timezone thì nhận gì

Mặc định là GMT. Mốc đầu của ngày 01/10 khi đó là 00:00 UTC, tức 07:00 tại Việt Nam. Bảng ghép với đơn hàng giờ địa phương sẽ lệch bảy tiếng mà không có lỗi nào hiện ra. Đây là lỗi im lặng phổ biến nhất của API này.

Truyền timezone rồi so lại

Lab gọi lại với timezone Asia/Ho_Chi_Minh. Response ghi utc_offset_seconds 25200 và abbreviation GMT+7. Mốc 07:00, 08:00, 09:00 có giá trị 28.1, 29.5, 30.9, đúng bằng ba mốc đầu của bản GMT. Phép so này xác nhận dữ liệu không đổi, chỉ nhãn giờ đổi.

b = requests.get(B, params=dict(p, timezone="Asia/Ho_Chi_Minh"), timeout=60).json()
print(a["hourly"]["temperature_2m"][0:3])
print(b["hourly"]["time"][7:10], b["hourly"]["temperature_2m"][7:10])
assert a["hourly"]["temperature_2m"][0:3] == b["hourly"]["temperature_2m"][7:10]

Assert này đáng giữ trong test của pipeline. Nó bắt đúng lỗi lệch múi giờ mà mắt thường rất khó thấy.

Đổi đơn vị ngay tại API

Tham số temperature_unit, wind_speed_unit, precipitation_unit đổi đơn vị trả về. Lab đặt fahrenheit, ms, inch và nhận hourly_units °F, inch, m/s, hai giá trị đầu 82.0 và 82.2. Bảng nên đọc đơn vị từ hourly_units của chính response, không tự ghi cứng trong code.

Chọn tọa độ, thời gian và biến historical weather trong Open-Meteo archive API

Khoảng ngày và biến nên chốt trước khi gọi, vì chúng quyết định dữ liệu đến từ model nào.

Khoảng ngày được phép

Lab xin ngày tương lai 20/11/2026 và nhận HTTP 400 với thông điệp start_date ngoài khoảng 1940-01-01 tới 2026-11-05. Thông điệp cho biết luôn mốc cuối là ngày gọi. Lỗi kiểu này dễ đọc và script có thể ghi thẳng vào log.

Biến sai thì lỗi ra sao

Lab xin biến khong_co_bien và nhận HTTP 400. Thân lỗi có trường reason, nhưng nội dung là chuỗi kỹ thuật về việc không khởi tạo được kiểu biến. Thông điệp này không gợi ý tên đúng. Script nên kiểm danh sách biến từ tài liệu trước khi gọi, đừng chờ API nhắc.

Hourly và daily

Hourly là chuỗi theo giờ. Daily là tổng hợp theo ngày, và tài liệu ghi rằng tham số timezone là bắt buộc khi xin daily. Lý do đơn giản: một "ngày" phụ thuộc múi giờ. Lab xin temperature_2m_max từ 28/10 tới 05/11 với giờ Việt Nam và nhận đủ chín ngày.

Ngày gần hiện tại

Mảng daily trả tới 05/11, chính ngày gọi, với giá trị 29.4. Ngày đó chưa kết thúc tại thời điểm lab chạy. Theo bảng tài liệu, IFS cập nhật mỗi sáu giờ không trễ, còn ERA5 trễ khoảng năm ngày. Vì vậy vài ngày gần nhất có thể khác sau khi nguồn cập nhật, và pipeline nên tải lại cửa sổ này.

Bảng bộ dữ liệu theo tài liệu

Bảng: Bảng bộ dữ liệu theo tài liệu

Bộ dữ liệu

Vùng

Độ phân giải

Khoảng thời gian

Cập nhật

ECMWF IFS

Toàn cầu

9 km, theo giờ

2017 tới nay

6 giờ, không trễ

ERA5

Toàn cầu

0.25°, khoảng 25 km

1940 tới nay

Ngày, trễ 5 ngày

ERA5-Land

Toàn cầu

0.1°, khoảng 11 km

1950 tới nay

Ngày, trễ 5 ngày

CERRA

Châu Âu

5 km

1985 tới 06/2021

Không cập nhật

Chọn theo mục tiêu

Trang tài liệu khuyên chọn ERA5 hoặc ERA5-Land khi cần dữ liệu nhất quán qua nhiều thập kỷ. Lý do là một bộ dữ liệu thống nhất tránh được bước nhảy do đổi nguồn. Khi cần chi tiết gần đây, IFS có độ phân giải cao hơn. Mỗi lựa chọn nên được ghi lại kèm lý do.

Ghi nhịp gọi cho khoảng dài

Mỗi lời gọi lịch sử nhiều năm trả mảng lớn. Header của lab ghi X-RateLimit-Cost 1.0 cho hai ngày, ba biến. Tài liệu không phải chỗ lab đọc được công thức chi phí, nên script nên đọc header này cho khoảng thật. Chia theo năm giúp lỗi mạng chỉ phải tải lại một phần.

Nhiều điểm trong một lời gọi

Trang tài liệu có chế độ danh sách tọa độ và hộp bao. Lab chưa thử chế độ này. Với vài chục điểm, gọi tuần tự từng tọa độ dễ kiểm hơn vì mỗi response có tọa độ lưới riêng.

Ghi model, dataset cùng timezone và unit khi dùng Open-Meteo archive API

Cùng một giờ, cùng một tọa độ, các model cho số khác nhau. Phần này là lý do cột model không thể bỏ.

Thử năm giá trị models

Model khác số khác

Model khác số khác

Lab gọi cùng khoảng ngày với năm giá trị models và giờ tự động theo vị trí. Bảng dưới là output thật cho ba giờ đầu ngày 01/10/2026 tại Hà Nội, theo giờ địa phương.

Bảng: Thử năm giá trị models

models

Tọa độ ô lưới

Nhiệt độ ba giờ đầu

Mưa ba giờ đầu

best_match

21.05448, 105.898476

27.8, 27.9, 27.5

0.0, 0.0, 0.0

ecmwf_ifs

21.05448, 105.898476

27.8, 27.9, 27.5

0.0, 0.0, 0.0

era5

21.0, 105.75

28.3, 28.1, 28.0

0.0, 0.0, 0.0

era5_land

21.0, 105.899994

26.8, 26.6, 26.9

None, None, None

cerra

lỗi

No data is available for this location

không có

Ba điều rút ra từ bảng

Nhiệt độ lệch tới 1.5 độ giữa era5 và era5_land tại cùng thời điểm, với ô lưới khác nhau. Era5_land trả None cho mưa trong lần gọi này, nên một biến có thể thiếu theo model. Cerra báo lỗi vì chỉ phủ châu Âu. Không có model nào được gọi là đúng ở đây, vì lab chưa so với quan trắc.

Best match không phải một bộ dữ liệu cố định

Tài liệu nói mặc định Best Match kết hợp IFS, ERA5 và ERA5-Land. Tại ngày lab thử, best_match trùng với ecmwf_ifs. Với năm 2005, bộ IFS chưa có nên nguồn sẽ khác. Một chuỗi nhiều năm dùng mặc định có thể đổi nguồn giữa chừng. Muốn so nhiều thập kỷ thì chỉ định model cố định.

Cột nguồn tối thiểu

Mỗi lần gọi nên ghi một dòng vào bảng nguồn. Dòng đó có model yêu cầu, tọa độ gửi, tọa độ trả, elevation, timezone, utc_offset_seconds, ngày gọi. Bảng dữ liệu chỉ cần trỏ về id của lần gọi. Cách này gọn hơn việc lặp các cột đó trên mọi dòng giờ.

import json, datetime as D
 
def source_row(req, res):
    return {
        "called_at": D.datetime.now(D.timezone.utc).isoformat(timespec="seconds"),
        "model": req.get("models", "best_match"),
        "lat_req": req["latitude"], "lon_req": req["longitude"],
        "lat_grid": res["latitude"], "lon_grid": res["longitude"],
        "elevation": res["elevation"], "timezone": res["timezone"],
        "offset_s": res["utc_offset_seconds"],
        "units": json.dumps(res["hourly_units"], ensure_ascii=False),
    }

Hàm này là ví dụ của lab, chạy được trên response ở trên. Cột units lưu nguyên khối hourly_units để không mất thông tin khi đổi đơn vị sau này.

Xử lý lỗi nằm trong JSON

Với cerra, thứ cần đọc đầu tiên là cặp error và reason trong JSON. Script nên kiểm error trước khi truy cập hourly. Nếu không, lỗi hiện ra là KeyError rất khó hiểu ở một dòng xa hơn. Bắt lỗi sớm thì log nói đúng nguyên nhân.

Giá trị None trong chuỗi

Era5_land cho thấy mảng có thể chứa None. Python đọc thành None, pandas thành NaN. Không điền bằng 0 cho biến mưa, vì 0 nghĩa là không mưa còn None nghĩa là không có số. Đây là khác biệt quyết định với cột lượng mưa cộng dồn.

Ghi nguồn theo giấy phép

Điều khoản ghi dữ liệu của gói miễn phí theo CC BY 4.0, nên bảng công bố phải ghi nguồn. Ngoài Open-Meteo, bài công bố nên nhắc model như ERA5 khi dùng nó. Phần này chỉ tốn một dòng chú thích nhưng thường bị quên.

Chuẩn hóa giờ UTC, giờ địa phương và kiểm DST với Open-Meteo archive API

Đây là phát hiện đáng giá nhất của lab, và nó không ảnh hưởng tới Việt Nam nhưng ảnh hưởng tới mọi bảng có nhiều quốc gia.

Phép thử Berlin

Độ lệch cố định

Độ lệch cố định

Đức đổi giờ ngày 29/03/2026 và 25/10/2026. Lab gọi hai ngày đó với timezone Europe/Berlin. Cả hai đều trả 24 mốc giờ và có mốc 02:00, trong khi đồng hồ Đức không có 02:00 ngày 29/03. Cả hai response ghi utc_offset_seconds 3600 và GMT+1.

Phép thử tháng 7

Tháng 7 tại Berlin phải là GMT+2. Lab gọi 01/07/2026 hai lần. Bản GMT có bốn giá trị từ mốc 10:00 là 22.8, 24.4, 24.9, 26.0. Bản Europe/Berlin có bốn giá trị cùng vị trí là 21.2, 22.8, 24.4, 24.9, tức chỉ dời một giờ, và offset vẫn là 3600.

Tài liệu nói gì

Tài liệu giải thích rõ: timestamp ISO 8601 dùng một độ lệch cố định, là utc_offset_seconds của múi giờ tại lúc gọi. Lab gọi vào tháng 11 nên Berlin đang ở GMT+1, và độ lệch đó áp lên cả tháng 7. Đây là hành vi được ghi, không phải lỗi. Nhưng mốc 10:00 tháng 7 trong response không phải 10:00 trên đồng hồ Berlin.

Hệ quả cho bảng nhiều nước

Nếu anh em ghép giờ này với đơn hàng tại Đức theo giờ đồng hồ, mùa hè sẽ lệch một giờ. Tệ hơn, cùng một lời gọi chạy vào tháng 7 sẽ cho nhãn khác lời gọi chạy vào tháng 11. Hai lần tải cùng khoảng ngày có thể không khớp nhãn giờ.

Cách làm đúng

Luôn tải theo GMT hoặc unixtime, rồi tự đổi sang múi giờ đích bằng thư viện có cơ sở dữ liệu múi giờ. Python có zoneinfo cho việc này. Giờ UTC là khóa, giờ địa phương là cột tính ra. Việt Nam không có DST nên Asia/Ho_Chi_Minh an toàn, nhưng quy trình chung vẫn nên giữ một cách.

import datetime as D
from zoneinfo import ZoneInfo
 
p = dict(latitude=52.52, longitude=13.41, start_date="2026-07-01",
         end_date="2026-07-01", hourly="temperature_2m", timeformat="unixtime")
a = requests.get(B, params=p, timeout=60).json()
for t, v in list(zip(a["hourly"]["time"], a["hourly"]["temperature_2m"]))[10:12]:
    u = D.datetime.fromtimestamp(t, D.timezone.utc)
    print(u.isoformat(), u.astimezone(ZoneInfo("Europe/Berlin")).isoformat(), v)

Tài liệu mô tả timeformat unixtime là số giây từ 1970. Lab chạy phần chính bằng chuỗi ISO, đoạn unixtime trên là ví dụ triển khai theo tài liệu. Trên Windows, zoneinfo cần gói tzdata nếu hệ thống thiếu dữ liệu múi giờ.

Dùng chuỗi ISO thì đổi ra sao

Khi đã có chuỗi ISO không kèm độ lệch, anh em cộng utc_offset_seconds ngược lại để ra UTC. Vì độ lệch cố định, phép trừ này đúng cho mọi dòng. Đây là cách API gợi ý khi nói muốn tái tạo ngày giờ thì dùng utc_offset_seconds.

Daily có bị ảnh hưởng

Tài liệu cũng nói độ lệch đó áp cho ranh giới ngày của daily. Với Berlin mùa hè, ngày tổng hợp lệch một giờ so với ngày đồng hồ. Sai khác trên nhiệt độ cao nhất thường nhỏ, nhưng lượng mưa cộng ngày có thể đổi khi trận mưa rơi gần nửa đêm. Lab chưa đo mức chênh này.

Ghép với bảng đơn hàng

Đơn hàng tại Việt Nam thường lưu giờ địa phương hoặc UTC. Anh em đưa cả hai bên về UTC rồi ghép theo mốc giờ tròn. Nếu đơn có phút, làm tròn xuống đầu giờ theo một quy ước ghi rõ. Biến mưa là một lượng cộng trong khung giờ, nên anh em đọc mô tả biến trên trang tài liệu trước khi ghép để chọn đúng phía.

Bảng kiểm nhanh múi giờ

Bảng: Bảng kiểm nhanh múi giờ

Tình huống

Hành vi lab thấy

Việc cần làm

Không truyền timezone

GMT, offset 0

Ghi rõ UTC

Asia/Ho_Chi_Minh

Offset 25200 quanh năm

Dùng được trực tiếp

Europe/Berlin tháng 7 gọi tháng 11

Offset 3600, không phải 7200

Tải UTC, tự đổi

Ngày đổi giờ

Vẫn 24 mốc đều

Không suy ra DST từ response

Nêu rõ dữ liệu grid model và giới hạn so với quan trắc trạm trong Open-Meteo archive API

Dữ liệu sạch và đều không có nghĩa đó là số đo tại chỗ. Phần này giúp anh em viết chú thích đúng.

Lưới khác trạm thế nào

Lưới khác trạm

Lưới khác trạm

Trạm đo một điểm thật, có thể thiếu ngày, có cờ chất lượng. Ô lưới là giá trị đại diện cho một vùng từ 9 km tới khoảng 25 km. Trong một ô có thể có sông, đô thị và cánh đồng. Giá trị của ô không phân biệt được nhiệt độ trong ngõ phố với nhiệt độ ở bãi sông.

Tài liệu gọi đây là gì

Trang tài liệu dùng cụm gap-free, tức không có khoảng trống, và nói dữ liệu đến từ tái phân tích. Không khoảng trống là ưu điểm cho phân tích, nhưng cũng là lý do người đọc dễ tưởng đó là đo thật. Chú thích bảng nên có cụm "dữ liệu mô hình theo lưới".

Câu nên viết và không nên viết

Nên viết: "Nhiệt độ theo ERA5, ô lưới gần Hà Nội, truy vấn ngày 05/11/2026". Không nên viết: "Nhiệt độ đo tại Hà Nội". Không nên hứa số liệu cho một địa chỉ nhà hay một cửa hàng cụ thể. Một câu chú thích đúng tránh được tranh cãi về sau.

Mưa là biến khó nhất

Mưa thay đổi rất mạnh trong khoảng vài km, nên ô lưới dễ khác trải nghiệm tại chỗ. Khi dùng cho bài toán bán hàng, biến này hợp hơn ở mức "giờ có mưa trong vùng". Nếu cần chính xác tại điểm, anh em cần trạm hoặc radar, và phải tìm nguồn phù hợp.

Khi nào cần đối chiếu trạm

Nếu con số sẽ đi vào báo cáo cho khách, nên chọn vài ngày đối chiếu với một trạm gần. Bài NOAA trong cụm này có cách lấy dữ liệu trạm GHCND. Lab chưa làm phép so đó, nên bài không có sai số. Phép so cần thống nhất múi giờ và mốc đầu cuối của ngày.

Đô thị và độ cao

Ô lưới Hà Nội có độ cao 19 m, không phản ánh tòa nhà. Với vùng núi, chênh độ cao giữa ô lưới và điểm thật lớn hơn nhiều. Anh em nên so elevation trả về với độ cao điểm thật, và ghi chênh lệch vào bảng nguồn nếu trên vài chục mét.

Giới hạn dùng thương mại

Điều khoản ghi gói miễn phí dành cho dùng phi thương mại, dưới 10000 lượt mỗi ngày, 5000 mỗi giờ, 600 mỗi phút. Header của lab hiện X-RateLimit-Limit 600 và cửa sổ 60 giây, khớp điều khoản. Pipeline cho sản phẩm thương mại phải dùng gói trả phí của Open-Meteo hoặc tự vận hành theo giấy phép. Bài toán bán hàng ở đầu bài thuộc nhóm cần đọc kỹ điều này.

Cách đọc header giới hạn

Lab thấy X-RateLimit-Remaining 584 sau khoảng 16 lượt, X-RateLimit-Reset dạng epoch. Script đọc Remaining trước khi gọi tiếp, tạm dừng khi gần về 0. Như vậy tốt hơn chờ lỗi rồi mới xử lý.

Đường tải và vai trò proxy với Open-Meteo archive API

Phần này giữ phần mạng đơn giản, vì nguồn này không cần gì phức tạp.

Tải theo năm và ghi manifest

Chia khoảng dài theo năm, mỗi lời gọi một tệp JSON thô. Manifest ghi tham số, ngày gọi và hash nội dung. Lần sau chỉ tải lại vài tuần gần nhất, vì đó là phần có thể đổi. Dữ liệu cũ của ERA5 ít khi đổi, nhưng nên kiểm hash theo tháng.

import hashlib, pathlib, time, json
 
def fetch_year(y, base):
    q = dict(base, start_date=f"{y}-01-01", end_date=f"{y}-12-31")
    r = requests.get(B, params=q, timeout=120)
    r.raise_for_status()
    d = r.json()
    if d.get("error"):
        raise RuntimeError(d.get("reason"))
    p = pathlib.Path(f"raw/{y}.json")
    p.parent.mkdir(exist_ok=True)
    p.write_bytes(r.content)
    time.sleep(2)
    return {"year": y, "sha256": hashlib.sha256(r.content).hexdigest(),
            "remaining": r.headers.get("X-RateLimit-Remaining")}

Đoạn này là ví dụ triển khai, lab chỉ chạy các lời gọi ngắn hơn. Tên thư mục raw và cách chia năm là quy ước tự đặt.

Proxy có cần không

Open-Meteo gọi thẳng được và không cần khóa ở gói miễn phí. Điều khoản ghi giới hạn áp theo IP và ứng dụng, và nói rõ có thể chặn ứng dụng lạm dụng. Đổi IP để vượt giới hạn là vi phạm tinh thần điều khoản, nên không phải cách làm. Cách đặt nhịp hợp lý có ở bài rate limit API khi dùng proxy.

Khi hạ tầng buộc đi qua proxy

Một số mạng doanh nghiệp chỉ cho ra ngoài qua proxy cố định. Khi đó anh em khai báo ở tầng session, chuỗi theo định dạng proxy. Phần xử lý múi giờ và ghép bảng chạy offline, không cần mạng. Vai trò proxy trong thu thập dữ liệu có ở bài Web Scraping proxy là gì.

Nếu tác vụ khác cần IP trong nước, anh em có thể mua proxy Việt Nam tại trang chủ ProxyVN.

Đọc response thành bảng dài

Response của API ở dạng cột: một mảng time và mỗi biến một mảng cùng độ dài. Bảng nghiệm thu lại ở dạng dài, mỗi dòng một biến tại một giờ. Chuyển dạng ngay ở bước nạp giúp phần sau không phụ thuộc vào tên biến. Anh em nên kiểm độ dài các mảng bằng nhau trước khi ghép, vì mảng lệch là dấu hiệu response bị cắt.

def to_rows(res, source_id):
    h, u = res["hourly"], res["hourly_units"]
    n = len(h["time"])
    out = []
    for var in h:
        if var == "time":
            continue
        assert len(h[var]) == n, var
        for t, v in zip(h["time"], h[var]):
            out.append({"time": t, "variable": var, "value": v,
                        "unit": u[var], "source_id": source_id})
    return out

Hai ngày, ba biến của lab cho 144 dòng theo cách này, vì 48 mốc giờ nhân ba biến. Giá trị None đi thẳng vào bảng, không bị lọc. Như vậy phép đếm giá trị thiếu ở bước sau vẫn chính xác.

Kiểm số dòng theo khoảng ngày

Số mốc giờ kỳ vọng bằng số ngày nhân 24 với dữ liệu theo giờ. Lab thấy 48 cho hai ngày và 24 cho cả hai ngày đổi giờ tại Berlin. Một phép assert đơn giản theo công thức này bắt được response bị thiếu. Nó cũng nhắc người đọc rằng response không phản ánh ngày 23 giờ hay 25 giờ trên đồng hồ địa phương.

Khóa phiên bản

Lab chạy Python 3.12.10, requests 2.34.2. Đường dẫn có v1. Model mới có thể được thêm, nên cấu hình ghi model cụ thể và ngày chốt. Giữ một JSON mẫu nhỏ làm test đọc cho parser.

Đầu ra nghiệm thu: bảng giờ UTC, local, biến, đơn vị và nguồn model của Open-Meteo archive API

Mục cuối chốt bảng và danh sách kiểm trước khi dùng số.

Schema của bảng

Nghiệm thu bảng giờ

Nghiệm thu bảng giờ

Bảng: Schema của bảng

Cột

Ví dụ thật

Ghi chú

time_utc

2026-10-01T00:00Z

Khóa thời gian

time_local

2026-10-01T07:00+07:00

Tính từ UTC

variable

temperature_2m

Tên gốc

value

28.1

Không làm tròn

unit

°C

Lấy từ hourly_units

source_id

12

Trỏ tới bảng nguồn

Danh sách kiểm

  • Múi giờ: giá trị bản GMT và bản giờ địa phương khớp sau khi dời.
  • Model: có tên model, không để trống kể cả khi dùng mặc định.
  • Tọa độ: có cả tọa độ gửi và tọa độ ô lưới.
  • Đơn vị: đọc từ response, không ghi cứng.
  • Giá trị thiếu: None giữ nguyên, không đổi thành 0.
  • Chú thích: ghi là dữ liệu mô hình theo lưới, kèm ngày truy vấn.

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

Từ lab có thể viết rằng tọa độ trả về là tâm ô lưới cách điểm gửi vài km. Các model cho số khác nhau ở cùng giờ. Timestamp dùng độ lệch cố định tại lúc gọi. Không nên viết model nào chính xác hơn, vì lab chưa so với quan trắc.

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

Lab chưa chạy chế độ nhiều tọa độ, chưa tải một năm đầy đủ, chưa đo chênh daily do DST. Đoạn unixtime lấy từ tài liệu. Lab chưa thử các biến ngoài nhiệt độ, mưa, gió và chưa thử ERA5-Ensemble.

Tải theo UTC, ghi model và tọa độ ô lưới, đọc đơn vị từ response. Ba việc đó giữ bảng thời tiết không lệch giờ và không bị hiểu thành số đo tại trạm.

Open-Meteo archive API: câu hỏi thường gặp

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

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

Không, với gói miễn phí phi thương mại. Dùng thương mại thì cần gói trả phí theo điều khoản.

Vì sao tọa độ trả về khác tọa độ gửi?

Vì API chọn ô lưới gần nhất của model. Tọa độ trả về là tâm ô đó, nên mỗi model có thể trả một tọa độ khác.

Dữ liệu này có phải đo tại Hà Nội không?

Không. Đây là dữ liệu mô hình cho ô lưới gần điểm đó. Muốn số đo tại trạm thì dùng nguồn quan trắc.

Nên dùng best_match hay chọn model?

Dùng model cố định khi cần so nhiều năm. Best_match kết hợp nhiều nguồn nên hợp cho tra nhanh.

Vì sao giờ mùa hè ở châu Âu bị lệch một tiếng?

API dùng một độ lệch cố định tại lúc gọi cho cả khoảng ngày. Hãy tải theo GMT rồi tự đổi múi giờ.

Ngày gần đây có đổi số không?

Có thể. Một số nguồn trễ vài ngày, nên pipeline nên tải lại vài tuần gần nhất.

Giá trị None nên xử lý sao?

Giữ là thiếu. Đừng đổi thành 0, nhất là với biến mưa.

Proxy có giúp tải nhanh hơn không?

Không phải mục đích. Giới hạn là chính sách của nhà cung cấp, và script nên đặt nhịp đúng.

Open-Meteo archive API và những điều cần nhớ

Open-Meteo archive API cho lịch sử thời tiết đều và dễ dùng khi anh em tải theo UTC, ghi model, giữ tọa độ ô lưới và đọc đơn vị từ response. Đừng gọi đó là số đo tại trạm. Proxy.vn - Nhà cung cấp dịch vụ proxy chất lượng hàng đầu Việt Nam khuyên anh em kiểm múi giờ trước khi ghép bảng từ Open-Meteo archive API.

TIN TỨC LIÊN QUAN