fix(B04): .cpg 없는 도엽 dbf = cp949 로 읽음 · 병합 캐시 열쇠에 파서 판 번호 (PLAN 561-1)

- 도엽 파서 — zip 안 .cpg 가 없으면 encoding cp949 (latin-1 로 읽어 「등고수치」 칸 이름이 깨지던 흠)
- 병합 열쇠 {"sheets", "parser"} — B04 · D03 둘 다 · 옛 깨진 병합본은 다음 받기 때 다시 지음
- 새 지킴 시험 test_561_1 — .cpg 없는 cp949 견본 → 등고수치 읽힘
- 재현(4250c7bc tmp 사본) — 2026 구간 지형면 0 셀 → 201,088 셀 · 등고수치 빈 선 5,280 → 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-27 19:58:56 +09:00
co-authored by Claude Opus 5.5
parent 6d4964ae55
commit 70d3a69847
4 changed files with 90 additions and 5 deletions
+7 -2
View File
@@ -526,9 +526,14 @@ def download_geodata(
# 선정에서 빠진 zip은 쓰이지 않으므로 정리한다(다른 지역 잔재 포함).
prune_sheets(sheet_store, sheet_grid)
# 확보된 도엽을 레이어별 병합 GeoJSON으로 산출 — 열쇠(도엽 번호 목록)가 같으면 스킵
from B04_PreProcess.B04_PreProcess_Engine_SheetParser import PARSER_VERSION
# 확보된 도엽을 레이어별 병합 GeoJSON으로 산출 — 열쇠(도엽 번호 목록 · 파서 판)가 같으면 스킵
merge_key_path = processed_dir / "sheet_merge.key.json"
merge_key = {"sheets": sorted(str(item) for item in sheet_result["available"])}
merge_key = {
"sheets": sorted(str(item) for item in sheet_result["available"]),
"parser": PARSER_VERSION,
}
if sheet_result["available"] and (
rebuild
or not any(processed_dir.glob("도엽_*.geojson"))
@@ -37,6 +37,10 @@ SHEET_LAYERS: dict[str, tuple[str, str]] = {
# 산출 파일 접두사 (기존 processed/의 국가 GIS geojson과 구분)
_OUTPUT_PREFIX = "도엽"
# 파서 판 번호 — 병합 캐시 열쇠에 넣음 · 읽는 법이 바뀌면 올려 옛 병합본을 다시 지음
PARSER_VERSION = 2
# .cpg 없는 도엽 dbf 의 글자 인코딩(국토지리정보원 배포본)
DBF_FALLBACK_ENCODING = "cp949"
def _read_layer_from_zip(
@@ -57,7 +61,9 @@ def _read_layer_from_zip(
with tempfile.TemporaryDirectory() as td:
for n in wanted:
(Path(td) / Path(n).name).write_bytes(zf.read(n))
gdf = gpd.read_file(Path(td) / f"{member_base}.shp")
has_cpg = any(Path(n).suffix.lower() == ".cpg" for n in wanted)
options = {} if has_cpg else {"encoding": DBF_FALLBACK_ENCODING}
gdf = gpd.read_file(Path(td) / f"{member_base}.shp", **options)
if gdf.empty:
return None