fix(detect): masquer artefacts noms de fichiers DPI et variante BACTERIO N° venue
- RE_SCAN_FILENAME_ARTIFACT : masque le suffixe numérique des noms de fichiers internes type EXT2-[IPP]-2300249096.TIF qui fuyaient en sortie. - _RE_VENUE_BEFORE_IPP : variante BACTERIO observée en production où le N° venue est rejeté plusieurs lignes après le libellé, juste avant IPP. Détection en phase 0i. - _RE_FINAL_VENUE_BEFORE_IPP : nettoyage final pour le résiduel du même layout BACTERIO si le numéro a survécu jusqu'à process_pdf. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -710,6 +710,10 @@ RE_VENUE_SEJOUR = re.compile(
|
|||||||
r"|num[ée]ro\s+de\s+(?:venue|séjour))\s*[:\-]?\s*(\d{4,})",
|
r"|num[ée]ro\s+de\s+(?:venue|séjour))\s*[:\-]?\s*(\d{4,})",
|
||||||
re.IGNORECASE,
|
re.IGNORECASE,
|
||||||
)
|
)
|
||||||
|
RE_SCAN_FILENAME_ARTIFACT = re.compile(
|
||||||
|
r"\b([A-Z]{2,}\d*-)(\[[A-Z_]+\]|[A-Za-z0-9]{6,})-(\d{6,})(\.(?:TIF|TIFF|PDF|JPG|JPEG|PNG))\b",
|
||||||
|
re.IGNORECASE,
|
||||||
|
)
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PiiHit:
|
class PiiHit:
|
||||||
@@ -2344,6 +2348,17 @@ def _apply_trackare_hits_to_text(text: str, audit: List[PiiHit], cfg: Dict[str,
|
|||||||
text = re.sub(rf"\b{escaped}\b", placeholder, text)
|
text = re.sub(rf"\b{escaped}\b", placeholder, text)
|
||||||
# Aussi gérer les formats avec astérisques (*640000162*)
|
# Aussi gérer les formats avec astérisques (*640000162*)
|
||||||
text = re.sub(rf"\*{escaped}\*", placeholder, text)
|
text = re.sub(rf"\*{escaped}\*", placeholder, text)
|
||||||
|
# Artefacts fréquents dans les DPI scannés : noms de fichiers internes de type
|
||||||
|
# EXT2-[IPP]-2300249096.TIF. Le suffixe numérique doit être masqué aussi.
|
||||||
|
def _repl_scan_artifact(m: re.Match) -> str:
|
||||||
|
middle = m.group(2)
|
||||||
|
if middle.startswith("[") and middle.endswith("]"):
|
||||||
|
middle_masked = middle
|
||||||
|
else:
|
||||||
|
middle_masked = PLACEHOLDERS["IPP"]
|
||||||
|
return f"{m.group(1)}{middle_masked}-{PLACEHOLDERS['DOSSIER']}{m.group(4)}"
|
||||||
|
|
||||||
|
text = RE_SCAN_FILENAME_ARTIFACT.sub(_repl_scan_artifact, text)
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
@@ -2472,6 +2487,14 @@ def anonymise_document_regex(pages_text: List[str], tables_lines: List[List[str]
|
|||||||
)
|
)
|
||||||
for m in _RE_VENUE_REVERSE.finditer(full_raw):
|
for m in _RE_VENUE_REVERSE.finditer(full_raw):
|
||||||
audit.append(PiiHit(-1, "NDA", m.group(1), PLACEHOLDERS["NDA"]))
|
audit.append(PiiHit(-1, "NDA", m.group(1), PLACEHOLDERS["NDA"]))
|
||||||
|
# Variante BACTERIO observée en production : "N° venue" puis DDN / nom, puis
|
||||||
|
# numéro de venue juste avant la ligne IPP.
|
||||||
|
_RE_VENUE_BEFORE_IPP = re.compile(
|
||||||
|
r"N[°o]?\s*venue\s*[:\-]?\s*\n(?:[^\n]*\n){0,3}\s*(\d{6,10})\s*\n\s*(?:I\.?P\.?P\.?|IPP)\s*[:\-]?",
|
||||||
|
re.IGNORECASE,
|
||||||
|
)
|
||||||
|
for m in _RE_VENUE_BEFORE_IPP.finditer(full_raw):
|
||||||
|
audit.append(PiiHit(-1, "NDA", m.group(1), PLACEHOLDERS["NDA"]))
|
||||||
|
|
||||||
# Phase 0i : règles d'administration actives sur identifiants.
|
# Phase 0i : règles d'administration actives sur identifiants.
|
||||||
_apply_admin_identifier_hits(full_raw, audit, cfg)
|
_apply_admin_identifier_hits(full_raw, audit, cfg)
|
||||||
@@ -4209,6 +4232,17 @@ def process_pdf(
|
|||||||
return prefix + PLACEHOLDERS["NOM"] + "/" + PLACEHOLDERS["NOM"]
|
return prefix + PLACEHOLDERS["NOM"] + "/" + PLACEHOLDERS["NOM"]
|
||||||
final_text = _RE_REF_INITIALS.sub(_clean_ref_initials, final_text)
|
final_text = _RE_REF_INITIALS.sub(_clean_ref_initials, final_text)
|
||||||
|
|
||||||
|
# 3e) Layout BACTERIO résiduel : le numéro de venue peut survivre s'il est
|
||||||
|
# rejeté plusieurs lignes après le libellé, juste avant "IPP : [IPP]".
|
||||||
|
_RE_FINAL_VENUE_BEFORE_IPP = re.compile(
|
||||||
|
r"(N[°o]?\s*venue\s*:\s*\n(?:[^\n]*\n){0,6}?)(\d{6,10})(\s*\n\s*IPP\s*:\s*\[IPP\])",
|
||||||
|
re.IGNORECASE,
|
||||||
|
)
|
||||||
|
def _clean_final_venue_before_ipp(m):
|
||||||
|
anon.audit.append(PiiHit(-1, "NDA", m.group(2), PLACEHOLDERS["NDA"]))
|
||||||
|
return m.group(1) + PLACEHOLDERS["NDA"] + m.group(3)
|
||||||
|
final_text = _RE_FINAL_VENUE_BEFORE_IPP.sub(_clean_final_venue_before_ipp, final_text)
|
||||||
|
|
||||||
# 4) Consolidation : propager les PII détectés sur toutes les pages (page=-1)
|
# 4) Consolidation : propager les PII détectés sur toutes les pages (page=-1)
|
||||||
# pour que la redaction PDF les cherche partout (sidebar répété, etc.)
|
# pour que la redaction PDF les cherche partout (sidebar répété, etc.)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user