#!/usr/bin/env python3 """Create a CSV inventory from the iqon.com page sitemap. SPEC: reports/live-captures/2026-05-20/page-sitemap.xml Compliance date: 2026-05-20 Launch type: manual SEO inventory generation Registry: iqon sitemap inventory parser """ from __future__ import annotations import csv import sys import urllib.parse import xml.etree.ElementTree as ET from collections import Counter from pathlib import Path SITEMAP_NS = {"sm": "http://www.sitemaps.org/schemas/sitemap/0.9"} def classify_url(url: str, duplicate_count: int) -> tuple[str, str]: parsed = urllib.parse.urlparse(url) decoded_path = urllib.parse.unquote(parsed.path) if duplicate_count > 1: return "duplicate", "canonicalize_or_remove_duplicate" if "%" in parsed.path: return "encoded_multilingual", "decide_hreflang_or_noindex_redirect" if decoded_path in {"/homepage/", "/hows-business/"}: return "legacy_home_alias", "redirect_to_root_or_rewrite" if "retail-wholesail" in decoded_path: return "typo_slug", "redirect_to_correct_spelling" if decoded_path == "/services-solutions/": return "thin_landing", "rewrite_as_services_overview" if decoded_path == "/contact/": return "contact", "verify_contact_data_then_keep" if decoded_path == "/": return "homepage", "rewrite_homepage_metadata_and_content" return "service_or_content", "review_rewrite_or_merge" def iter_urls(path: Path) -> list[dict[str, str]]: tree = ET.parse(path) urls: list[dict[str, str]] = [] for node in tree.findall("sm:url", SITEMAP_NS): loc_node = node.find("sm:loc", SITEMAP_NS) lastmod_node = node.find("sm:lastmod", SITEMAP_NS) if loc_node is None or not loc_node.text: continue loc = loc_node.text.strip() parsed = urllib.parse.urlparse(loc) urls.append( { "url": loc, "decoded_path": urllib.parse.unquote(parsed.path), "lastmod": (lastmod_node.text.strip() if lastmod_node is not None and lastmod_node.text else ""), } ) counts = Counter(item["url"] for item in urls) for item in urls: duplicate_count = counts[item["url"]] item["duplicate_count"] = str(duplicate_count) item["class"], item["recommended_action"] = classify_url(item["url"], duplicate_count) return urls def main() -> int: if len(sys.argv) not in {2, 3}: print("Usage: iqon-sitemap-inventory.py [output.csv]", file=sys.stderr) return 2 rows = iter_urls(Path(sys.argv[1])) output = open(sys.argv[2], "w", newline="", encoding="utf-8") if len(sys.argv) == 3 else sys.stdout writer = csv.DictWriter( output, fieldnames=["url", "decoded_path", "lastmod", "duplicate_count", "class", "recommended_action"], ) writer.writeheader() writer.writerows(rows) if output is not sys.stdout: output.close() return 0 if __name__ == "__main__": raise SystemExit(main())