L o a d i n g
Как создать простого чат-бота для интернет-магазина книг на Django с использованием JSON Сайты

В этой статье мы разберем, как добавить простого чат-бота на сайт интернет-магазина книг, используя 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
  1. Откройте http://127.0.0.1:8000/ и протестируйте бота:
    • Введите "толстой" → бот предложит "Война и мир".
    • Введите "python" → бот найдет "Программирование на Python".
    • Введите "книга" → бот скажет "Ничего не найдено".

Итог

Вы создали простого чат-бота для интернет-магазина книг! Он работает без базы данных, использует JSON для хранения каталога и fuzzywuzzy для поиска с учетом опечаток. Этот подход легко масштабировать: добавьте больше книг в books.json или улучшите интерфейс, добавив кнопки или автодополнение.

Если у вас есть вопросы или идеи для улучшения, пишите в комментариях!

Написать комментарий

Вы можете оставить комментарий автору статьи Обязательные поля помечены *