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,})",
|
||||
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
|
||||
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)
|
||||
# Aussi gérer les formats avec astérisques (*640000162*)
|
||||
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
|
||||
|
||||
|
||||
@@ -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):
|
||||
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.
|
||||
_apply_admin_identifier_hits(full_raw, audit, cfg)
|
||||
@@ -4209,6 +4232,17 @@ def process_pdf(
|
||||
return prefix + PLACEHOLDERS["NOM"] + "/" + PLACEHOLDERS["NOM"]
|
||||
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)
|
||||
# pour que la redaction PDF les cherche partout (sidebar répété, etc.)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user