From 813e5790837050c4de4b760fa380a4b1d504beed Mon Sep 17 00:00:00 2001 From: dirkwa Date: Wed, 25 Mar 2026 13:29:15 +1200 Subject: [PATCH] feat: add script to generate NOAA ENC S-57 charts catalog Scrapes https://charts.noaa.gov/ENCs/ENCs.shtml and generates NOAA_ENC_Catalog.xml with all US state/territory ENC downloads. --- noaa_enc.py | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++ noaa_enc.sh | 27 ++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100755 noaa_enc.py create mode 100755 noaa_enc.sh diff --git a/noaa_enc.py b/noaa_enc.py new file mode 100755 index 0000000..21957d7 --- /dev/null +++ b/noaa_enc.py @@ -0,0 +1,72 @@ +#!/usr/bin/python3 +"""Script to process the NOAA ENC download page and convert it to the XML catalog format +Part of the ChartCatalogs project +Copyright (c) 2026 Dirk +Licensed under GPLv2 or, at your will later version +""" + +import re +import sys +from ChartCatalogs.RncChartCatalog import RncChartCatalog +from ChartCatalogs.Chart import Chart +from datetime import datetime + +STATE_NAMES = { + 'AK': 'Alaska', 'AL': 'Alabama', 'AQ': 'Antarctica', + 'BS': 'Bahamas', 'CA': 'California', 'CT': 'Connecticut', + 'DE': 'Delaware', 'FL': 'Florida', 'FM': 'Micronesia', + 'GA': 'Georgia', 'GT': 'Guatemala', 'HI': 'Hawaii', + 'HT': 'Haiti', 'ID': 'Idaho', 'IL': 'Illinois', + 'IN': 'Indiana', 'LA': 'Louisiana', 'MA': 'Massachusetts', + 'MD': 'Maryland', 'ME': 'Maine', 'MH': 'Marshall Islands', + 'MI': 'Michigan', 'MN': 'Minnesota', 'MS': 'Mississippi', + 'NC': 'North Carolina', 'NH': 'New Hampshire', 'NJ': 'New Jersey', + 'NV': 'Nevada', 'NY': 'New York', 'OH': 'Ohio', + 'OR': 'Oregon', 'PA': 'Pennsylvania', 'PO': 'Pacific Ocean', + 'PR': 'Puerto Rico', 'PW': 'Palau', 'RI': 'Rhode Island', + 'SC': 'South Carolina', 'SP': 'Spratly Islands', 'TX': 'Texas', + 'VA': 'Virginia', 'VT': 'Vermont', 'WA': 'Washington', + 'WI': 'Wisconsin', +} + +BASE_URL = 'https://charts.noaa.gov/ENCs' + +# Pattern: ...XX......SIZE MBDATE +ENTRY_RE = re.compile( + r'href="([A-Z]{2})_ENCs\.zip"[^>]*>.*?' + r'.*?' + r'(\d+) MB' + r'(\d{2}/\d{2}/\d{4}\s+\d{2}:\d{2}:\d{2})', + re.DOTALL +) + + +def main(): + with open(sys.argv[1]) as f: + html = f.read() + + entries = [] + for m in ENTRY_RE.finditer(html): + code = m.group(1) + size_mb = int(m.group(2)) + ts = datetime.strptime(m.group(3), '%m/%d/%Y %H:%M:%S') + name = STATE_NAMES.get(code, code) + entries.append((code, name, size_mb, ts)) + + catalog = RncChartCatalog() + catalog.title = 'NOAA ENC Charts (S-57) by State' + + for code, name, size_mb, ts in entries: + chart = Chart() + chart.number = code + chart.title = '%s (%d MB)' % (name, size_mb) + chart.chart_format = 'Electronic Navigational Chart, S-57' + chart.url = '%s/%s_ENCs.zip' % (BASE_URL, code) + chart.zipfile_ts = ts + catalog.add_chart(chart) + + catalog.print_xml() + + +if __name__ == '__main__': + main() diff --git a/noaa_enc.sh b/noaa_enc.sh new file mode 100755 index 0000000..eb92032 --- /dev/null +++ b/noaa_enc.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Script to download NOAA ENC charts list and convert it to the XML catalog format +# +# Part of the ChartCatalogs project +# Copyright (c) 2026 Dirk +# Licensed under GPLv2 or, at your will later version +# + +if [ -z "${CHARTCATALOGS_TARGETDIR}" ]; then + TARGETDIR='.' +else + TARGETDIR="${CHARTCATALOGS_TARGETDIR}" +fi + +CATALOGNAME='NOAA_ENC_Catalog.xml' + +WORKDIR='/tmp' +rm -f ${WORKDIR}/noaa_enc.html +if wget -q -O ${WORKDIR}/noaa_enc.html https://charts.noaa.gov/ENCs/ENCs.shtml; then + python3 ./noaa_enc.py ${WORKDIR}/noaa_enc.html > ${WORKDIR}/${CATALOGNAME} + if xmllint --noout ${WORKDIR}/${CATALOGNAME} 2>&1 >/dev/null; then + cat ${WORKDIR}/${CATALOGNAME} | xmllint --format - > ${TARGETDIR}/${CATALOGNAME} + rm ${WORKDIR}/${CATALOGNAME} + fi + rm -f ${WORKDIR}/noaa_enc.html +fi