DLP
This commit is contained in:
@@ -35,3 +35,19 @@ def validate_snils(value: str) -> bool:
|
||||
if expected == 100:
|
||||
expected = 0
|
||||
return checksum == expected
|
||||
|
||||
|
||||
def validate_passport(value: str) -> bool:
|
||||
"""
|
||||
Lightweight Russian passport validator:
|
||||
- expects 10 digits (series+number), optionally with spaces
|
||||
- rejects obvious invalid placeholders (all same digit, all zeros)
|
||||
"""
|
||||
digits = re.sub(r"\D", "", value)
|
||||
if len(digits) != 10:
|
||||
return False
|
||||
if digits == "0000000000":
|
||||
return False
|
||||
if len(set(digits)) == 1:
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
"description": "СНИЛС"
|
||||
},
|
||||
"passport": {
|
||||
"regex": "\\b\\d{4}\\s?\\d{6}\\b",
|
||||
"checksum": "none",
|
||||
"regex": "\\b\\d{4}\\s\\d{6}\\b",
|
||||
"checksum": "passport",
|
||||
"description": "Паспорт РФ"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@ from __future__ import annotations
|
||||
import json
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
from checksum_validator import validate_inn, validate_snils
|
||||
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
|
||||
from checksum_validator import validate_inn, validate_passport, validate_snils
|
||||
|
||||
|
||||
def _validate(kind: str, value: str) -> bool:
|
||||
@@ -14,11 +16,17 @@ def _validate(kind: str, value: str) -> bool:
|
||||
return validate_inn(value)
|
||||
if kind == "snils":
|
||||
return validate_snils(value)
|
||||
if kind == "passport":
|
||||
return validate_passport(value)
|
||||
return True
|
||||
|
||||
|
||||
def match_text(text: str, dictionary_path: str) -> list[dict[str, Any]]:
|
||||
rules = json.loads(pathlib.Path(dictionary_path).read_text(encoding="utf-8"))
|
||||
def _load_json(path: str) -> dict[str, Any]:
|
||||
return json.loads(pathlib.Path(path).read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def match_text_with_dictionary(text: str, dictionary_path: str) -> list[dict[str, Any]]:
|
||||
rules = _load_json(dictionary_path)
|
||||
results: list[dict[str, Any]] = []
|
||||
for name, rule in rules.items():
|
||||
regex = re.compile(rule["regex"])
|
||||
@@ -36,3 +44,40 @@ def match_text(text: str, dictionary_path: str) -> list[dict[str, Any]]:
|
||||
}
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def match_text_with_regex_pack(text: str, regex_pack_path: str) -> list[dict[str, Any]]:
|
||||
pack = _load_json(regex_pack_path)
|
||||
results: list[dict[str, Any]] = []
|
||||
entries: list[dict[str, Any]] = []
|
||||
if isinstance(pack.get("rules"), list):
|
||||
entries = [e for e in pack["rules"] if isinstance(e, dict)]
|
||||
elif isinstance(pack.get("patterns"), dict):
|
||||
entries = [{"id": k, **v} for k, v in pack["patterns"].items() if isinstance(v, dict)]
|
||||
|
||||
for entry in entries:
|
||||
rule_id = entry.get("id") or entry.get("name") or "regex-rule"
|
||||
regex = re.compile(entry["regex"])
|
||||
for m in regex.finditer(text):
|
||||
results.append(
|
||||
{
|
||||
"name": rule_id,
|
||||
"description": entry.get("description", rule_id),
|
||||
"value": m.group(0),
|
||||
"start": m.start(),
|
||||
"end": m.end(),
|
||||
"severity": entry.get("severity", "medium"),
|
||||
}
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def match_text(
|
||||
text: str,
|
||||
dictionary_path: str | None = None,
|
||||
regex_pack_path: str | None = None,
|
||||
) -> dict[str, list[dict[str, Any]]]:
|
||||
return {
|
||||
"dictionary_matches": match_text_with_dictionary(text, dictionary_path) if dictionary_path else [],
|
||||
"regex_matches": match_text_with_regex_pack(text, regex_pack_path) if regex_pack_path else [],
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ from pathlib import Path
|
||||
from PIL import Image
|
||||
import pytesseract
|
||||
|
||||
from dictionary_matcher import match_text
|
||||
|
||||
|
||||
def extract_text(image_path: str) -> str:
|
||||
path = Path(image_path)
|
||||
@@ -13,3 +15,16 @@ def extract_text(image_path: str) -> str:
|
||||
return ""
|
||||
img = Image.open(path)
|
||||
return pytesseract.image_to_string(img, lang="rus+eng")
|
||||
|
||||
|
||||
def analyze_screenshot(
|
||||
image_path: str,
|
||||
dictionary_path: str | None = None,
|
||||
regex_pack_path: str | None = None,
|
||||
) -> dict:
|
||||
text = extract_text(image_path)
|
||||
if not text:
|
||||
return {"text": "", "dictionary_matches": [], "regex_matches": []}
|
||||
result = match_text(text=text, dictionary_path=dictionary_path, regex_pack_path=regex_pack_path)
|
||||
result["text"] = text
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user