В этой статье мы разберем, как добавить простого чат-бота на сайт интернет-магазина книг, используя Django, JSON для хранения данных и библиотеку fuzzywuzzy для поиска с учетом опечаток. Бот будет помогать пользователям находить книги по ключевым словам, не требуя базы данных — все данные будут храниться в JSON-файле. Мы создадим интерфейс в стиле чата, где пользователь вводит запрос, а бот отвечает в реальном времени, предлагая подходящие книги из каталога.
Что нам понадобится
- Django: фреймворк для веб-разработки.
- Python 3.x: убедитесь, что он установлен.
- fuzzywuzzy: библиотека для нечеткого поиска (установите через pip install fuzzywuzzy).
- JSON: файл с каталогом книг.
- Базовые знания HTML, CSS и JavaScript.
Шаг 1: Настройка проекта
Предположим, у вас уже есть Django-проект. Если нет, создайте его:
django-admin startproject bookstore
cd bookstore
python manage.py startapp shop
Добавьте приложение shop в INSTALLED_APPS в bookstore/settings.py:
INSTALLED_APPS = [
...
'shop',
]
Шаг 2: Создание JSON-каталога книг
Создайте файл books.json в корне проекта (/bookstore/books.json) с данными о книгах:
{
"books": [
{
"url": "/books/1",
"title": "Война и мир",
"keywords": ["война", "мир", "толстой", "классика"],
"description": "Эпический роман Льва Толстого о судьбах людей в эпоху Наполеона"
},
{
"url": "/books/2",
"title": "Гарри Поттер и Философский камень",
"keywords": ["гарри", "поттер", "фэнтези", "магия"],
"description": "Первая книга о приключениях юного волшебника"
},
{
"url": "/books/3",
"title": "Программирование на Python",
"keywords": ["python", "программирование", "код", "it"],
"description": "Руководство по изучению Python для начинающих"
}
]
}
- url: ссылка на страницу книги.
- title: название книги.
- keywords: ключевые слова для поиска.
- description: краткое описание.
Шаг 3: Логика поиска с fuzzywuzzy
Создайте файл shop/book_search.py с классом для поиска:
import json
from fuzzywuzzy import fuzz
class BookSearch:
def __init__(self, json_path):
with open(json_path, 'r', encoding='utf-8') as f:
self.data = json.load(f)['books']
def search(self, query, limit=3):
query = query.lower().strip()
results = []
for book in self.data:
score = 0
for keyword in book['keywords']:
if fuzz.partial_ratio(query, keyword) > 70: # Порог схожести
score += fuzz.partial_ratio(query, keyword)
if fuzz.partial_ratio(query, book['title'].lower()) > 70:
score += fuzz.partial_ratio(query, book['title'].lower())
if score > 0:
results.append({
'url': book['url'],
'title': book['title'],
'description': book['description'],
'score': score
})
return sorted(results, key=lambda x: x['score'], reverse=True)[:limit]
- Класс BookSearch загружает JSON и ищет книги по запросу, используя fuzzywuzzy для нечеткого соответствия.
Шаг 4: Context Processor для передачи данных
Создайте shop/context_processors.py:
import os
from django.conf import settings
from shop.book_search import BookSearch
def book_search(request):
query = request.GET.get('s', '')
results = []
if query:
json_path = os.path.join(settings.BASE_DIR, 'books.json')
search_instance = BookSearch(json_path)
results = search_instance.search(query)
return {
'search_query': query,
'search_results': results,
}
Добавьте его в settings.py:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
...
'shop.context_processors.book_search',
],
},
},
]
Шаг 5: Шаблон с чат-ботом
Создайте templates/base.html:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Интернет-магазин книг</title>
<link rel="stylesheet" href="/static/css/styles.css">
</head>
<body>
<div class="site-wrapper">
{% block content %}{% endblock %}
</div>
</body>
</html>
Создайте templates/shop/home.html:
{% extends "base.html" %}
{% block content %}
<div class="atbs-search-full On">
<div id="search-dialog" class="dialog-box">
<div id="dialog-content" class="chat-container">
{% if search_results %}
<ul>
{% for result in search_results %}
<li><a href="{{ result.url }}">{{ result.title }}</a> - {{ result.description }}</li>
{% endfor %}
</ul>
{% elif search_query %}
<p>Ничего не найдено для "{{ search_query }}"</p>
{% else %}
<div class="message bot-message">
<p>Привет, любитель книг!</p>
<p>Напиши, какую книгу ищешь, и я помогу найти!</p>
</div>
{% endif %}
</div>
</div>
<form id="search-form" action="" method="get" onsubmit="return false;">
<input name="s" class="form-control" placeholder="Напиши, что ищешь..." type="text" value="">
<span id="atbs-search-remove"><i class="mdicon mdicon-close"></i></span>
</form>
</div>
<script>
const searchInput = document.querySelector('input[name="s"]');
const dialogBox = document.getElementById('search-dialog');
const dialogContent = document.getElementById('dialog-content');
const removeBtn = document.getElementById('atbs-search-remove');
const searchForm = document.getElementById('search-form');
window.addEventListener('load', function() {
dialogBox.style.display = 'block';
});
searchForm.addEventListener('submit', function(e) {
e.preventDefault();
const query = searchInput.value.trim();
if (query) {
const userMessage = document.createElement('div');
userMessage.classList.add('message', 'user-message');
userMessage.innerHTML = `<p>${query}</p>`;
dialogContent.appendChild(userMessage);
searchInput.value = '';
const url = new URL(window.location.href);
url.searchParams.set('s', query);
fetch(url, {
method: 'GET',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => {
if (!response.ok) throw new Error('Network response was not ok');
return response.text();
})
.then(html => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const newDialogContent = doc.querySelector('#dialog-content');
const botMessage = document.createElement('div');
botMessage.classList.add('message', 'bot-message');
if (newDialogContent && newDialogContent.innerHTML.trim()) {
botMessage.innerHTML = newDialogContent.innerHTML;
} else {
botMessage.innerHTML = '<p>Ошибка: нет данных</p>';
}
dialogContent.appendChild(botMessage);
dialogBox.scrollTop = dialogBox.scrollHeight;
})
.catch(error => {
const errorMessage = document.createElement('div');
errorMessage.classList.add('message', 'bot-message');
errorMessage.innerHTML = '<p>Ошибка при поиске</p>';
dialogContent.appendChild(errorMessage);
dialogBox.scrollTop = dialogBox.scrollHeight;
});
}
});
removeBtn.addEventListener('click', function() {
searchInput.value = '';
dialogContent.innerHTML = `
<div class="message bot-message">
<p>Привет, любитель книг!</p>
<p>Напиши, какую книгу ищешь, и я помогу найти!</p>
</div>
`;
const url = new URL(window.location.href);
url.searchParams.delete('s');
window.history.pushState({}, document.title, url);
});
</script>
{% endblock %}
Шаг 6: Стилизация
Создайте static/css/styles.css:
.atbs-search-full {
background: rgba(0, 0, 0, 0.9);
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.dialog-box {
background: #fff;
padding: 20px;
border-radius: 5px;
max-width: 600px;
width: 100%;
max-height: 70vh;
overflow-y: auto;
}
.chat-container {
display: flex;
flex-direction: column;
gap: 10px;
}
.message {
padding: 10px;
border-radius: 5px;
max-width: 80%;
}
.bot-message {
background: #f0f0f0;
align-self: flex-start;
}
.user-message {
background: #d1e7dd;
align-self: flex-end;
text-align: right;
}
.form-control {
width: 600px;
padding: 10px;
font-size: 16px;
border: none;
border-radius: 5px;
margin-top: 20px;
}
#atbs-search-remove {
cursor: pointer;
margin-left: 10px;
color: #fff;
}
Подключите статику в settings.py:
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
Шаг 7: View и URL
Создайте простую вьюху в shop/views.py:
from django.shortcuts import render
def home(request):
return render(request, 'shop/home.html')
Настройте urls.py:
# bookstore/urls.py
from django.urls import path
from shop.views import home
urlpatterns = [
path('', home, name='home'),
]
Шаг 8: Запуск
Установите зависимости
pip install fuzzywuzzy
Выполните миграции и запустите сервер:
python manage.py makemigrations
python manage.py migrate
python manage.py runserver
- Откройте http://127.0.0.1:8000/ и протестируйте бота:
- Введите "толстой" → бот предложит "Война и мир".
- Введите "python" → бот найдет "Программирование на Python".
- Введите "книга" → бот скажет "Ничего не найдено".
Итог
Вы создали простого чат-бота для интернет-магазина книг! Он работает без базы данных, использует JSON для хранения каталога и fuzzywuzzy для поиска с учетом опечаток. Этот подход легко масштабировать: добавьте больше книг в books.json или улучшите интерфейс, добавив кнопки или автодополнение.
Если у вас есть вопросы или идеи для улучшения, пишите в комментариях!
Написать комментарий