You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.6 KiB
90 lines
2.6 KiB
""" |
|
Laddar ned motioner från riksdagens öppna data som ZIP-arkiv med JSON-filer. |
|
|
|
Arkiven är uppdelade i fyraårsperioder (förankrade vid 1998; allt före ligger |
|
i 1990-1997) och uppdateras dagligen: |
|
|
|
https://data.riksdagen.se/dataset/dokument/mot-{range}.json.zip |
|
|
|
Varje arkiv innehåller en JSON-fil per motion (dokumentstatus-kuvert med |
|
metadata + fulltext som HTML). Extraheras till motioner/mot-{range}/. |
|
|
|
Backfill (alla perioder 1990→): python scripts/download_motions.py |
|
Används av sync_motions.py för daglig uppdatering av aktuell period. |
|
""" |
|
|
|
import logging |
|
import os |
|
import sys |
|
from io import BytesIO |
|
from urllib.request import urlopen |
|
from zipfile import ZipFile |
|
|
|
os.chdir("/home/lasse/riksdagen") |
|
sys.path.append("/home/lasse/riksdagen") |
|
|
|
logging.basicConfig( |
|
level=logging.INFO, |
|
format="%(asctime)s [%(levelname)s] %(message)s", |
|
) |
|
logger = logging.getLogger(__name__) |
|
|
|
RANGES = [ |
|
"1990-1997", |
|
"1998-2001", |
|
"2002-2005", |
|
"2006-2009", |
|
"2010-2013", |
|
"2014-2017", |
|
"2018-2021", |
|
"2022-2025", |
|
] |
|
URL_TEMPLATE = "https://data.riksdagen.se/dataset/dokument/mot-{r}.json.zip" |
|
MOTIONS_DIR = "motioner" |
|
|
|
|
|
def get_current_range(session_year: int) -> str: |
|
"""Fyraårsperiod förankrad vid 1998; allt före 1998 ligger i 1990-1997.""" |
|
if session_year < 1998: |
|
return "1990-1997" |
|
start = session_year - ((session_year - 1998) % 4) |
|
return f"{start}-{start + 3}" |
|
|
|
|
|
def download_range(r: str, force: bool = False) -> str: |
|
""" |
|
Laddar ned och extraherar arkivet för en period till motioner/mot-{r}/. |
|
Hoppar över om mappen redan är ifylld, om inte force=True (töms först). |
|
""" |
|
dir_path = os.path.join(MOTIONS_DIR, f"mot-{r}") |
|
|
|
if os.path.exists(dir_path) and os.listdir(dir_path): |
|
if not force: |
|
logger.info(f"Skipping {dir_path}, already exists and is not empty.") |
|
return dir_path |
|
for f in os.listdir(dir_path): |
|
os.remove(os.path.join(dir_path, f)) |
|
|
|
os.makedirs(dir_path, exist_ok=True) |
|
url = URL_TEMPLATE.format(r=r) |
|
logger.info(f"Downloading {url} → {dir_path}") |
|
|
|
with urlopen(url) as resp: |
|
with ZipFile(BytesIO(resp.read())) as zf: |
|
zf.extractall(dir_path) |
|
|
|
count = len(os.listdir(dir_path)) |
|
logger.info(f"Extracted {count} files to {dir_path}") |
|
return dir_path |
|
|
|
|
|
def download_all(force: bool = False) -> None: |
|
for r in RANGES: |
|
download_range(r, force=force) |
|
|
|
|
|
if __name__ == "__main__": |
|
if len(sys.argv) > 1: |
|
download_range(sys.argv[1], force="--force" in sys.argv) |
|
else: |
|
download_all()
|
|
|