|
| 1 | +# Analisi Fattibilità: Elenco Atti Correlati |
| 2 | + |
| 3 | +## Obiettivo |
| 4 | + |
| 5 | +Aggiungere un'opzione CLI per ottenere l'elenco degli atti correlati a una norma. |
| 6 | + |
| 7 | +## API Identificata |
| 8 | + |
| 9 | +### Endpoint |
| 10 | + |
| 11 | +``` |
| 12 | +GET https://www.normattiva.it/do/atto/vediAttiCorrelati |
| 13 | +``` |
| 14 | + |
| 15 | +### Parametri richiesti |
| 16 | + |
| 17 | +- `atto.dataPubblicazioneGazzetta`: data pubblicazione GU (formato: YYYY-MM-DD) |
| 18 | +- `atto.codiceRedazionale`: codice redazionale (es: 088G0458) |
| 19 | +- `currentSearch`: sempre "ricerca_avanzata_aggiornamenti" |
| 20 | + |
| 21 | +### Esempio chiamata |
| 22 | + |
| 23 | +```bash |
| 24 | +curl "https://www.normattiva.it/do/atto/vediAttiCorrelati?atto.dataPubblicazioneGazzetta=1988-09-12&atto.codiceRedazionale=088G0458¤tSearch=ricerca_avanzata_aggiornamenti" |
| 25 | +``` |
| 26 | + |
| 27 | +## Formato risposta |
| 28 | + |
| 29 | +L'API restituisce HTML con una tabella strutturata: |
| 30 | + |
| 31 | +```html |
| 32 | +<table id="rigaItem" summary="Aggiornamenti all'atto" class="tabella_elencoAgg"> |
| 33 | + <thead> |
| 34 | + <tr> |
| 35 | + <th>Progr.</th> |
| 36 | + <th>data pubblicazione</th> |
| 37 | + <th>atti correlati</th> |
| 38 | + </tr> |
| 39 | + </thead> |
| 40 | + <tbody> |
| 41 | + <tr> |
| 42 | + <td>1</td> |
| 43 | + <td>22/09/1989</td> |
| 44 | + <td> |
| 45 | + <a href="/atto/caricaDettaglioAtto?atto.dataPubblicazioneGazzetta=1989-09-22&atto.codiceRedazionale=089G0398"> |
| 46 | + DECRETO LEGISLATIVO 6 settembre 1989, n. 322 |
| 47 | + (in G.U. 22/09/1989, n.222) |
| 48 | + </a> |
| 49 | + Norme sul Sistema statistico nazionale... |
| 50 | + </td> |
| 51 | + </tr> |
| 52 | + <!-- altri atti... --> |
| 53 | + </tbody> |
| 54 | +</table> |
| 55 | +``` |
| 56 | + |
| 57 | +## Informazioni estratte per ogni atto correlato |
| 58 | + |
| 59 | +1. **Numero progressivo**: posizione nell'elenco |
| 60 | +2. **Data pubblicazione**: data GU (formato: DD/MM/YYYY) |
| 61 | +3. **Tipo atto**: DECRETO LEGISLATIVO, LEGGE, DECRETO DEL PRESIDENTE, ecc. |
| 62 | +4. **Data e numero**: es. "6 settembre 1989, n. 322" |
| 63 | +5. **Riferimento GU**: es. "G.U. 22/09/1989, n.222" |
| 64 | +6. **Descrizione**: testo descrittivo dell'atto |
| 65 | +7. **URL dettaglio**: link per accedere all'atto correlato |
| 66 | + - Contiene `atto.dataPubblicazioneGazzetta` e `atto.codiceRedazionale` |
| 67 | + |
| 68 | +## Integrazione nel progetto esistente |
| 69 | + |
| 70 | +### Parametri già disponibili |
| 71 | + |
| 72 | +Il progetto **già estrae** i parametri necessari in `normattiva_api.py:extract_params_from_normattiva_url()`: |
| 73 | + |
| 74 | +```python |
| 75 | +# Linee 147-160 |
| 76 | +params = {} |
| 77 | +match_gu = re.search(r'name="atto\.dataPubblicazioneGazzetta"[^>]*value="([^"]+)"', html) |
| 78 | +if match_gu: |
| 79 | + # Formato già YYYY-MM-DD (perfetto per l'API atti correlati!) |
| 80 | + params["dataGU"] = match_gu.group(1).replace("-", "") # YYYYMMDD per download XML |
| 81 | + |
| 82 | +match_codice = re.search(r'name="atto\.codiceRedazionale"[^>]*value="([^"]+)"', html) |
| 83 | +if match_codice: |
| 84 | + params["codiceRedaz"] = match_codice.group(1) |
| 85 | +``` |
| 86 | + |
| 87 | +**NOTA**: L'API `vediAttiCorrelati` richiede la data nel formato `YYYY-MM-DD`, mentre la funzione attuale converte in `YYYYMMDD` per il download XML. Servirà mantenere entrambi i formati. |
| 88 | + |
| 89 | +### Moduli da creare/modificare |
| 90 | + |
| 91 | +1. **Nuova funzione in `normattiva_api.py`**: |
| 92 | + ```python |
| 93 | + def fetch_related_acts(params, session=None, quiet=False): |
| 94 | + """ |
| 95 | + Recupera elenco atti correlati |
| 96 | +
|
| 97 | + Args: |
| 98 | + params: dict con dataPubblicazioneGazzetta (YYYY-MM-DD) e codiceRedazionale |
| 99 | + session: sessione requests (opzionale) |
| 100 | + quiet: se True, stampa solo errori |
| 101 | +
|
| 102 | + Returns: |
| 103 | + list: elenco dizionari con informazioni atti correlati |
| 104 | + """ |
| 105 | + ``` |
| 106 | + |
| 107 | +2. **Nuova opzione CLI in `cli.py`**: |
| 108 | + ```python |
| 109 | + parser.add_argument( |
| 110 | + '--related-acts', '--atti-correlati', |
| 111 | + action='store_true', |
| 112 | + help='Mostra elenco atti correlati (solo se input è URL)' |
| 113 | + ) |
| 114 | + ``` |
| 115 | + |
| 116 | +3. **Output formati supportati**: |
| 117 | + - **JSON**: lista strutturata di oggetti |
| 118 | + - **Markdown**: tabella o lista puntata |
| 119 | + - **Plain text**: lista semplice per pipe |
| 120 | + |
| 121 | +### Esempio output JSON |
| 122 | + |
| 123 | +```json |
| 124 | +[ |
| 125 | + { |
| 126 | + "numero_progressivo": 1, |
| 127 | + "data_pubblicazione": "22/09/1989", |
| 128 | + "tipo_atto": "DECRETO LEGISLATIVO", |
| 129 | + "data_atto": "6 settembre 1989", |
| 130 | + "numero_atto": "322", |
| 131 | + "riferimento_gu": "G.U. 22/09/1989, n.222", |
| 132 | + "titolo": "Norme sul Sistema statistico nazionale...", |
| 133 | + "url_dettaglio": "/atto/caricaDettaglioAtto?atto.dataPubblicazioneGazzetta=1989-09-22&atto.codiceRedazionale=089G0398", |
| 134 | + "url_normattiva": "https://www.normattiva.it/uri-res/N2Ls?urn:nir:stato:decreto.legislativo:1989-09-06;322", |
| 135 | + "parametri": { |
| 136 | + "dataPubblicazioneGazzetta": "1989-09-22", |
| 137 | + "codiceRedazionale": "089G0398" |
| 138 | + } |
| 139 | + } |
| 140 | +] |
| 141 | +``` |
| 142 | + |
| 143 | +### Esempio output Markdown |
| 144 | + |
| 145 | +```markdown |
| 146 | +# Atti correlati a LEGGE 23 agosto 1988, n. 400 |
| 147 | + |
| 148 | +## 1. DECRETO LEGISLATIVO 6 settembre 1989, n. 322 |
| 149 | + |
| 150 | +**Pubblicazione**: 22/09/1989 (G.U. n.222) |
| 151 | + |
| 152 | +Norme sul Sistema statistico nazionale e sulla riorganizzazione dell'Istituto nazionale di statistica... |
| 153 | + |
| 154 | +**URL**: [Visualizza su Normattiva](https://www.normattiva.it/uri-res/N2Ls?urn:nir:stato:decreto.legislativo:1989-09-06;322) |
| 155 | + |
| 156 | +--- |
| 157 | + |
| 158 | +## 2. DECRETO LEGISLATIVO 16 dicembre 1989, n. 418 |
| 159 | + |
| 160 | +... |
| 161 | +``` |
| 162 | + |
| 163 | +## Parsing HTML |
| 164 | + |
| 165 | +Libreria suggerita: **BeautifulSoup4** o **lxml** |
| 166 | + |
| 167 | +```python |
| 168 | +from bs4 import BeautifulSoup |
| 169 | + |
| 170 | +def parse_related_acts_html(html_content): |
| 171 | + """ |
| 172 | + Estrae atti correlati dalla risposta HTML |
| 173 | +
|
| 174 | + Args: |
| 175 | + html_content: HTML restituito dall'API |
| 176 | +
|
| 177 | + Returns: |
| 178 | + list: atti correlati come dizionari |
| 179 | + """ |
| 180 | + soup = BeautifulSoup(html_content, 'html.parser') |
| 181 | + table = soup.find('table', {'id': 'rigaItem'}) |
| 182 | + |
| 183 | + acts = [] |
| 184 | + for row in table.find('tbody').find_all('tr'): |
| 185 | + cells = row.find_all('td') |
| 186 | + |
| 187 | + # Estrai dati... |
| 188 | + prog = cells[0].get_text(strip=True) |
| 189 | + data = cells[1].get_text(strip=True) |
| 190 | + |
| 191 | + # Link e informazioni atto |
| 192 | + link = cells[2].find('a') |
| 193 | + # ... |
| 194 | + |
| 195 | + acts.append({...}) |
| 196 | + |
| 197 | + return acts |
| 198 | +``` |
| 199 | + |
| 200 | +## Dipendenze aggiuntive |
| 201 | + |
| 202 | +- `beautifulsoup4`: parsing HTML |
| 203 | +- `lxml`: parser veloce (opzionale, ma raccomandato) |
| 204 | + |
| 205 | +Aggiornare `setup.py`: |
| 206 | + |
| 207 | +```python |
| 208 | +install_requires=[ |
| 209 | + "requests>=2.25.0", |
| 210 | + "python-dotenv>=0.19.0", |
| 211 | + "beautifulsoup4>=4.9.0", |
| 212 | + "lxml>=4.6.0", # opzionale ma raccomandato |
| 213 | +] |
| 214 | +``` |
| 215 | + |
| 216 | +## Casi d'uso CLI |
| 217 | + |
| 218 | +```bash |
| 219 | +# 1. Mostra atti correlati come JSON |
| 220 | +normattiva2md --related-acts "https://www.normattiva.it/uri-res/N2Ls?urn:nir:stato:legge:1988-08-23;400" --format json |
| 221 | + |
| 222 | +# 2. Mostra atti correlati come Markdown |
| 223 | +normattiva2md --related-acts "https://www.normattiva.it/uri-res/N2Ls?urn:nir:stato:legge:1988-08-23;400" --format markdown |
| 224 | + |
| 225 | +# 3. Converti norma + salva atti correlati separatamente |
| 226 | +normattiva2md "URL" output.md --related-acts --related-acts-output atti_correlati.json |
| 227 | + |
| 228 | +# 4. Solo atti correlati, senza convertire la norma |
| 229 | +normattiva2md --related-acts-only "URL" > atti_correlati.json |
| 230 | +``` |
| 231 | + |
| 232 | +## Vantaggi |
| 233 | + |
| 234 | +1. ✅ **API esistente e funzionante**: già usata dal sito web |
| 235 | +2. ✅ **Parametri già disponibili**: estratti dalla pagina HTML |
| 236 | +3. ✅ **Nessuna autenticazione**: API pubblica |
| 237 | +4. ✅ **Struttura ben definita**: tabella HTML facilmente parsabile |
| 238 | +5. ✅ **Integrazione semplice**: riusa infrastruttura esistente (session, headers, timeout) |
| 239 | + |
| 240 | +## Limitazioni |
| 241 | + |
| 242 | +1. ⚠️ **Formato HTML**: richiede parsing (non JSON nativo) |
| 243 | +2. ⚠️ **Dipendenza aggiuntiva**: BeautifulSoup4 |
| 244 | +3. ⚠️ **Funziona solo da URL**: non da file XML locale (parametri non disponibili nell'XML) |
| 245 | + |
| 246 | +## Stima implementazione |
| 247 | + |
| 248 | +- **Complessità**: BASSA |
| 249 | +- **Tempo stimato**: 2-3 ore |
| 250 | +- **Modifiche necessarie**: |
| 251 | + - [ ] Aggiungere `beautifulsoup4` a `setup.py` |
| 252 | + - [ ] Creare funzione `fetch_related_acts()` in `normattiva_api.py` |
| 253 | + - [ ] Creare funzione `parse_related_acts_html()` per parsing |
| 254 | + - [ ] Aggiungere opzioni CLI in `cli.py` |
| 255 | + - [ ] Aggiungere formattatori output (JSON, Markdown, plain text) |
| 256 | + - [ ] Test con diversi tipi di atti |
| 257 | + - [ ] Documentazione README |
| 258 | + |
| 259 | +## Conclusione |
| 260 | + |
| 261 | +✅ **FATTIBILE** - L'implementazione è semplice e ben integrata con l'architettura esistente. |
| 262 | + |
| 263 | +L'API è pubblica, i parametri sono già estratti, e la struttura HTML è facilmente parsabile. L'unica dipendenza aggiuntiva è BeautifulSoup4, già ampiamente usata e mantenuta. |
| 264 | + |
| 265 | +## Prossimi passi |
| 266 | + |
| 267 | +1. Conferma con il maintainer se la feature è desiderata |
| 268 | +2. Decidere formati output preferiti (JSON, Markdown, CSV?) |
| 269 | +3. Implementare funzione base |
| 270 | +4. Aggiungere test |
| 271 | +5. Documentare nel README |
0 commit comments