Спам в веб-формах — это не просто раздражающий поток мусорных сообщений. Он засоряет почтовые ящики администраторов, перегружает системы уведомлений и может даже стать источником уязвимостей (например, через массовую отправку вредоносных ссылок). Традиционные методы борьбы, такие как CAPTCHA, регулярные выражения или чёрные списки слов, часто оказываются недостаточно гибкими: спамеры адаптируются, а легитимные пользователи страдают от неудобств.
Современный подход — использование нейронных сетей для анализа текста — позволяет добиться высокой точности в классификации "спам/не спам". В этой статье мы создадим модуль для Django-проекта, который:
- Обнаруживает спам в формах с помощью обученной модели.
- Блокирует отправку спам-сообщений на почту и их отображение в админке.
- Легко интегрируется в существующий проект.
Шаг 1: Понимание задачи и подготовка данных
Проблема в деталях
Когда пользователь отправляет форму (например, комментарий или заявку), сообщение обычно:
- Сохраняется в базе данных.
- Отображается в админ-панели Django.
- Отправляется на email администратору или пользователю.
Если это спам, все эти действия становятся лишними и нежелательными. Наша цель — остановить процесс на этапе проверки формы, если текст классифицирован как спам.
Подготовка данных
Для обучения модели нужен датасет с примерами спама и нормальных сообщений. Можно использовать:
- Открытые наборы данных, такие как "SMS Spam Collection" с Kaggle.
- Собственные данные, если у вас уже есть история сообщений.
Пример предобработки текста:
import nltk
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
nltk.download('punkt')
nltk.download('stopwords')
def preprocess_text(text):
tokens = word_tokenize(text.lower())
stop_words = set(stopwords.words('english')) # или другой язык
tokens = [word for word in tokens if word.isalnum() and word not in stop_words]
return ' '.join(tokens)
Шаг 2: Обучение нейронной сети
Для простоты возьмём модель на основе LSTM (долгая краткосрочная память), которая хорошо справляется с классификацией текста. Используем TensorFlow.
Код обучения
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, LSTM, Dense
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
# Пример данных
texts = ["buy cheap pills now", "hello, how are you", "free money click here"]
labels = [1, 0, 1] # 1 - спам, 0 - не спам
# Токенизация
tokenizer = Tokenizer(num_words=5000)
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)
padded_sequences = pad_sequences(sequences, maxlen=50)
# Модель
model = Sequential([
Embedding(input_dim=5000, output_dim=32, input_length=50),
LSTM(64),
Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(padded_sequences, np.array(labels), epochs=10)
# Сохранение
model.save('spam_detector.h5')
import pickle
with open('tokenizer.pkl', 'wb') as f:
pickle.dump(tokenizer, f)
Это базовая модель. Для реального проекта можно использовать предобученные трансформеры (например, BERT) через библиотеку transformers
.
Шаг 3: Интеграция в Django
Структура проекта
Добавим модуль spam_filter
в Django-проект:
myproject/
├── spam_filter/
│ ├── __init__.py
│ ├── models.py
│ ├── forms.py
│ ├── utils.py
│ └── admin.py
├── myproject/
└── manage.py
Утилиты для проверки спама
В spam_filter/utils.py
загрузим модель и создадим функцию классификации:
import numpy as np
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
import pickle
from . import preprocess_text
# Загрузка модели и токенайзера
model = load_model('spam_detector.h5')
with open('tokenizer.pkl', 'rb') as f:
tokenizer = pickle.load(f)
def is_spam(text):
processed_text = preprocess_text(text)
sequence = tokenizer.texts_to_sequences([processed_text])
padded = pad_sequences(sequence, maxlen=50)
prediction = model.predict(padded)[0][0]
return prediction > 0.5 # Порог для спама
Форма с проверкой
В spam_filter/forms.py
создадим форму, которая блокирует спам:
from django import forms
from .utils import is_spam
class CommentForm(forms.Form):
text = forms.CharField(widget=forms.Textarea)
def clean_text(self):
text = self.cleaned_data['text']
if is_spam(text):
raise forms.ValidationError("Сообщение похоже на спам и не будет отправлено.")
return text
Модель и админка
В spam_filter/models.py
определим модель для сообщений:
from django.db import models
class Comment(models.Model):
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
is_spam = models.BooleanField(default=False)
def __str__(self):
return self.text[:50]
В spam_filter/admin.py
скроем спам из админки:
from django.contrib import admin
from .models import Comment
@admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
list_display = ('text', 'created_at', 'is_spam')
list_filter = ('is_spam',)
def get_queryset(self, request):
# Показываем только не-спам в админке
return super().get_queryset(request).filter(is_spam=False)
Представление (view)
В spam_filter/views.py
обработаем форму и заблокируем отправку email:
from django.shortcuts import render
from django.core.mail import send_mail
from .forms import CommentForm
from .models import Comment
from .utils import is_spam
def submit_comment(request):
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
text = form.cleaned_data['text']
# Сохраняем только не-спам
comment = Comment.objects.create(text=text, is_spam=is_spam(text))
if not comment.is_spam:
send_mail(
'Новый комментарий',
text,
'from@example.com',
['admin@example.com'],
fail_silently=True,
)
return render(request, 'success.html')
else:
form = CommentForm()
return render(request, 'comment_form.html', {'form': form})
Шаблоны
templates/comment_form.html
:
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Отправить</button>
</form>
templates/success.html
:
<h1>Спасибо! Ваш комментарий принят.</h1>
Шаг 4: Блокировка спама на уровне системы
- База данных: Спам сохраняется с флагом
is_spam=True
, но не отображается в админке благодаря фильтру вCommentAdmin
. - Email: Уведомления отправляются только для записей с
is_spam=False
. - Пользовательский опыт: Если текст классифицирован как спам, пользователь видит ошибку формы и процесс останавливается.
Шаг 5: Оптимизация и улучшение
- Производительность: Для больших проектов модель можно вынести на отдельный сервис (например, через FastAPI) и вызывать через API.
- Обновление модели: Регулярно дообучайте модель на новых данных из вашей базы.
- Логирование: Добавьте логи для анализа ложных срабатываний.
Заключение
Мы создали модуль, который использует нейронную сеть для фильтрации спама в формах Django. Он не только защищает от нежелательного контента, но и предотвращает его попадание в админку и на почту, экономя ресурсы и время. Такой подход — это шаг к автоматизации и повышению качества веб-приложений.
Написать комментарий