aboutsummaryrefslogtreecommitdiff
path: root/src/rn.py
diff options
context:
space:
mode:
authorgdamms <damguillotin@gmail.com>2026-07-24 13:25:21 +0200
committergdamms <damguillotin@gmail.com>2026-07-24 13:25:21 +0200
commit9daf8e0fa5db84988679606c9b4c8f26ef463db1 (patch)
tree0e2a0df8912f65c0b22f9efab017312df9218c76 /src/rn.py
parent77aed43a99a295f3202063edefcb7ce01e011958 (diff)
downloaddog-friendly-data-9daf8e0fa5db84988679606c9b4c8f26ef463db1.tar.gz
dog-friendly-data-9daf8e0fa5db84988679606c9b4c8f26ef463db1.zip
clean the repo
Diffstat (limited to 'src/rn.py')
-rw-r--r--src/rn.py149
1 files changed, 85 insertions, 64 deletions
diff --git a/src/rn.py b/src/rn.py
index 0c6589c..c78f1c2 100644
--- a/src/rn.py
+++ b/src/rn.py
@@ -1,81 +1,102 @@
-import requests
+import argparse
+import json
import re
+import xml.etree.ElementTree as ET
+
+import requests
+
+from kml_utils import add_placemark, add_polygon, new_document, write_kml
+LIST_URL = "https://reserves-naturelles.org/reserves-naturelles/"
-def get_coordinates_from_url(url):
+
+def get_coordinates_from_url(url: str) -> list[tuple[float, float]] | None:
+ """Fetch a reserve page and extract its outer polygon ring.
+
+ Args:
+ url (str): URL of the reserve page.
+ Returns:
+ list[tuple[float, float]] | None: (longitude, latitude) points, or None if no
+ coordinates could be found on the page.
+ """
response = requests.get(url)
- regex = r"\[\[-?\d+\.\d+,-?\d+\.\d+\](?:,\[-?\d+\.\d+,-?\d+\.\d+\])+\]"
- matche = re.search(regex, response.text)
- if not matche:
+ match = re.search(
+ r"\[\[-?\d+\.\d+,-?\d+\.\d+\](?:,\[-?\d+\.\d+,-?\d+\.\d+\])+\]", response.text
+ )
+ if not match:
return None
- coordinates = eval(matche.group(0))
- return coordinates
+ return [tuple(point) for point in json.loads(match.group(0))]
+
+
+def get_reserves(list_url: str = LIST_URL) -> list[dict]:
+ """Fetch the reserves list page and extract each reserve's name and URL.
+
+ Args:
+ list_url (str, optional): URL of the reserves list page. Defaults to LIST_URL.
+ Returns:
+ list[dict]: One {"full_name", "name", "url"} entry per reserve found on the page.
+ """
+ response = requests.get(list_url)
+ items = re.findall(r"<li class=\"reserve\"[\s\S]*?</li>", response.text)
+
+ reserves = []
+ for item in items:
+ full_name_match = re.search(r"title=\"([^\"]+)\"", item)
+ name_match = re.search(r"class=\"rsv_nom\">([^<]+)<", item)
+ url_match = re.search(r"href=\"([^\"]+)\"", item)
+
+ if not full_name_match or not name_match or not url_match:
+ print(f"Skipping incomplete list entry: {item}")
+ continue
+
+ reserves.append(
+ {
+ "full_name": full_name_match.group(1),
+ "name": name_match.group(1),
+ "url": url_match.group(1),
+ }
+ )
+
+ return reserves
-response = requests.get("https://reserves-naturelles.org/reserves-naturelles/")
-regex = r"<li class=\"reserve\"[\s\S]*?</li>"
-matches = re.findall(regex, response.text)
+def scrape_reserves(list_url: str = LIST_URL) -> ET.Element:
+ """Scrape reserves-naturelles.org and build a KML tree with one Placemark per reserve.
-kml_file = open("reserves_naturelles.kml", "w", encoding="utf-8")
-kml_file.write("""<?xml version="1.0" encoding="UTF-8"?>
-<kml xmlns="http://www.opengis.net/kml/2.2">
- <Document>
- <name>RN</name>
-""")
+ Args:
+ list_url (str, optional): URL of the reserves list page. Defaults to LIST_URL.
+ Returns:
+ ET.Element: The root <kml> element.
+ """
+ root, document = new_document("RN")
+ reserves = get_reserves(list_url)
+ for i, reserve in enumerate(reserves):
+ coordinates = get_coordinates_from_url(reserve["url"])
+ if not coordinates:
+ print(f"No coordinates found for URL: {reserve['url']}")
+ continue
-for i, match in enumerate(matches):
+ placemark = add_placemark(
+ document,
+ name=reserve["name"],
+ description=f"{reserve['full_name']}<br/>{reserve['url']}",
+ )
+ add_polygon(placemark, coordinates)
- regex = r"title=\"([^\"]+)\""
- full_name = re.search(regex, match)
- if not full_name:
- print(f"Full name not found in the match: {match}")
- continue
- full_name = full_name.group(1)
+ print(f"Processed: {reserve['name']} ({i + 1:3d}/{len(reserves)})")
- regex = r"class=\"rsv_nom\">([^<]+)<"
- name = re.search(regex, match)
- if not name:
- print(f"Name not found in the match: {match}")
- continue
- name = name.group(1)
+ return root
- regex = r"href=\"([^\"]+)\""
- url = re.search(regex, match)
- if not url:
- print(f"URL not found in the match: {match}")
- continue
- url = url.group(1)
- coordinates = get_coordinates_from_url(url)
- if not coordinates:
- print(f"Coordinates not found for URL: {url}")
- continue
+def main():
+ parser = argparse.ArgumentParser(description="Scrape reserves-naturelles.org and export reserves to KML")
+ parser.add_argument("-o", "--output", default="reserves_naturelles.kml", help="Path to the output KML file")
+ args = parser.parse_args()
- kml_file.write(f"""
- <Placemark>
- <name>{name}</name>
- <description>
- {full_name}<br/>{url}
- </description>
- <Polygon>
- <outerBoundaryIs>
- <LinearRing>
- <coordinates>
-""")
- for coordinate in coordinates:
- kml_file.write(f" {coordinate[0]},{coordinate[1]},0\n")
- kml_file.write("""
- </coordinates>
- </LinearRing>
- </outerBoundaryIs>
- </Polygon>
- </Placemark>
-""")
-
- print(f"Processed: {name} ({i+1: 3d}/{len(matches)})")
+ root = scrape_reserves()
+ write_kml(root, args.output)
-kml_file.write("""
- </Document>
-</kml>""")
+if __name__ == "__main__":
+ main()