Проблема: Данные во всех форматах
Типичная компания содержит PII в
- 40% в PDF (контракты, истории, счета)
- 30% в Excel (листы расчета, отчеты, базы данных)
- 15% в Word (документы, письма, протоколы)
- 10% в сканированных изображениях (бумажные архивы)
- 5% в базах данных (ч/о, CRM)
Проблема: Разные форматы требуют разных инструментов для обнаружения PII.
Типовой сценарий GDPR нарушения
Компания A проводит GDPR аудит:
Проверяем базу данных: 500 записей PII найдено
Проверяем Word документы: 250 PII найдено
Проверяем PDF: 100 PII найдено
Проверяем Excel: 1,200 PII найдено (!)
Проверяем сканированные изображения: 300 PII найдено
Отчет: 2,350 найдено
Аудитор: "Вы пропустили Excel? Это 51% всех данных!"
Штраф GDPR: €500,000 за неправильный учет
Архитектура обнаружения по форматам
Слой 1: PDF обнаружение
import pdfplumber
from presidio_analyzer import AnalyzerEngine
analyzer = AnalyzerEngine()
def detect_pii_in_pdf(pdf_path):
results = []
with pdfplumber.open(pdf_path) as pdf:
for page_num, page in enumerate(pdf.pages):
# Извлекаем текст
text = page.extract_text()
# Анализируем
entities = analyzer.analyze(
text=text,
language='en'
)
results.append({
'page': page_num,
'text': text,
'entities': entities
})
return results
Слой 2: Excel обнаружение
import openpyxl
from presidio_analyzer import AnalyzerEngine
analyzer = AnalyzerEngine()
def detect_pii_in_excel(excel_path):
results = []
workbook = openpyxl.load_workbook(excel_path)
for sheet_name in workbook.sheetnames:
sheet = workbook[sheet_name]
for row_num, row in enumerate(sheet.iter_rows(), 1):
row_text = " ".join(
str(cell.value) for cell in row if cell.value
)
entities = analyzer.analyze(
text=row_text,
language='en'
)
if entities:
results.append({
'sheet': sheet_name,
'row': row_num,
'entities': entities
})
return results
Слой 3: Word обнаружение
from docx import Document
from presidio_analyzer import AnalyzerEngine
analyzer = AnalyzerEngine()
def detect_pii_in_word(docx_path):
results = []
doc = Document(docx_path)
for para_num, para in enumerate(doc.paragraphs):
entities = analyzer.analyze(
text=para.text,
language='en'
)
if entities:
results.append({
'paragraph': para_num,
'text': para.text,
'entities': entities
})
return results
Слой 4: Сканированные изображения (OCR)
import pytesseract
from PIL import Image
from presidio_analyzer import AnalyzerEngine
analyzer = AnalyzerEngine()
def detect_pii_in_scanned_image(image_path):
results = []
# Открываем изображение
image = Image.open(image_path)
# Извлекаем текст через OCR
text = pytesseract.image_to_string(image)
# Анализируем текст
entities = analyzer.analyze(
text=text,
language='en'
)
return {
'image': image_path,
'ocr_text': text,
'entities': entities
}
Проблемы per-format
PDF проблемы
| Проблема | Решение |
|---|---|
| Скрытый текст под изображениями | Используйте OCR |
| Зашифрованные PDF | Требует пароля |
| Неправильно кодированный текст | Попробуйте несколько кодировок |
| Текст как изображение | Необходим OCR |
Excel проблемы
| Проблема | Решение |
|---|---|
| Скрытые листы | Раскройте все листы |
| Скрытые колонки | Покажите все колонки |
| Формулы содержат PII | Проверьте формулы |
| Метаданные содержат PII | Очистите метаданные |
Word проблемы
| Проблема | Решение |
|---|---|
| Отслеживание изменений содержит PII | Удалите всю историю |
| Скрытый текст | Покажите скрытый текст |
| Комментарии содержат PII | Удалите все комментарии |
| Метаданные автора | Удалите метаданные |
Сканированные изображения проблемы
| Проблема | Решение |
|---|---|
| Низкое качество OCR | Улучшить изображение |
| Множественные языки | OCR на нескольких языках |
| Рукописный текст | Низкая точность OCR |
| Таблицы на изображении | Специальная таблица OCR |
Полная система обнаружения
import os
from pathlib import Path
class DocumentFragmentationScanner:
def __init__(self):
self.analyzer = AnalyzerEngine()
def scan_directory(self, directory_path):
all_results = {}
for file_path in Path(directory_path).rglob('*'):
if file_path.is_file():
file_ext = file_path.suffix.lower()
if file_ext == '.pdf':
all_results[str(file_path)] = self.detect_pii_in_pdf(str(file_path))
elif file_ext in ['.xlsx', '.xls']:
all_results[str(file_path)] = self.detect_pii_in_excel(str(file_path))
elif file_ext == '.docx':
all_results[str(file_path)] = self.detect_pii_in_word(str(file_path))
elif file_ext in ['.png', '.jpg', '.jpeg', '.tiff']:
all_results[str(file_path)] = self.detect_pii_in_scanned_image(str(file_path))
return all_results
def generate_report(self, scan_results):
total_files = len(scan_results)
total_entities = sum(
len(r.get('entities', []))
for file_results in scan_results.values()
for r in (file_results if isinstance(file_results, list) else [file_results])
)
return {
'total_files_scanned': total_files,
'total_pii_entities': total_entities,
'files_with_pii': [
file for file, results in scan_results.items()
if any(r.get('entities') for r in (results if isinstance(results, list) else [results]))
]
}
# Использование
scanner = DocumentFragmentationScanner()
results = scanner.scan_directory('/documents')
report = scanner.generate_report(results)
print(f"Найдено PII в {len(report['files_with_pii'])} файлах")
print(f"Всего PII сущностей: {report['total_pii_entities']}")
GDPR соответствие
Требуется
✅ Сканировать ВСЕ форматы документов ✅ Отслеживать какие данные где находятся ✅ Удалить PII согласно графику хранения ✅ Документировать процесс сканирования ✅ Регулярно пересканировать (quartile)
Вывод
Фрагментация документов означает, что 50%+ вашей PII может быть незащищенной. Сканируйте все форматы.