Наконец собрался написать вторую часть как и обещал в первой. В этой части хочется рассказать о клиентской стороне проекта.
Что используется:
Как говорил раньше проект полностью написан на Python (со вставками Cython'а). Вся информация о изображениях, пользователях, статистики — хранится в БД MySQL.
Для поиска (основного) и фильтра используется Sphinx-сервер. Клиент написанный для twisted txsphinx.
Для «лайков», кол-во просмотров изображения и кол-во скачиваний используется Redis. Так-же в Redis-е хранится топ-изображений (главная страница) и «похожие изображения» (страница самого изображения). Для twisted клиент txredis, найденный на просторах и немного доработанный под себя (пока не в паблике).
Веб: TwistedWeb с шаблонизатором Jinja2, рисуется все Bootsrap'ом и Jquery. Конец цепочки это Nginx.
Интересная часть:
Первое (и самое интересное) это было сделать фильтр изображений. Для начала был составлен список полей для поиска:
- Категории
- Минимальное разрешение изображения
- Ключевые слова
- Цвета
Фильтр решено было сделать с помощью Sphinx'а. Индексирование происходит через xmlpipe. Определение в sphinx очень простое:
source images {
type = xmlpipe2
xmlpipe_command = bin/sphinx.py --indexer=images
}
index images {
source = images
path = /var/lib/sphinx/data/images
morphology = stem_enru
charset_type = utf-8
min_word_len = 2
min_infix_len = 3
enable_star = 1
docinfo = extern
html_strip = 1
index_exact_words = 1
expand_keywords = 0
wordforms = images_wordforms.txt
}
Категории: MVA-атрибут, список ID. Так-же текстовый атрибут список названий категорий (для правильного поиска, прибавления веса результатам).
Минимальное разрешение изображения: Два атрибута width и height. Тут так-же все просто, поиск по диапазону каждого атрибута, от заданного пользователем до максимального (магическое число 10000).
Ключевые слова: Три текстовых атрибута title tags keywords. Title — заголовок изображения, результатам дается максимальный вес при попадании. Tags — список тегов изображения, средний вес. Keywords — набор ключевых слов (пользователь их не видит), взяты на странице изображения, могут содержать мусор. Маленький вес.
Цвета: Было самое сложное, расскажу подробней. Была создана палитра цветов {ID => RGB}. При добавлении изображения в базу, получаем список доминирующих цветов и приравниваем их к нашей палитре. Цвета изображения хранятся в БД с двумя значениями: ID цвета и процент занимаемый на изображении. В индексе десять MVA-атрибутов «c_X» где X — это номер от 0 до 9. В c_0 попадают все цвета изображения, в с_1 цвета с процентом >= 10, в c_2 цвета с процентом >= 20 и т.д.
Фильтр по цветам: При поиске изображений по цвету берутся все изображения у которых цвет находится в индексе c_1, далее считается вес цвета. При поиске по цвету с ID 2 (псевдокод):
setSelect('(IN(c_1,2)*1) + (IN(c_2,2)*1) + (IN(c_3,2)*1) + (IN(c_4,2)*1) + (IN(c_5,2)*1) + (IN(c_6,2)*1) + (IN(c_7,2)*1) + (IN(c_8,2)*1) + (IN(c_9,2)*1) AS colors_weight')
setOrder('colors_weight DESC')
Возможно поиск по цветам сделан не самым оптимальным способом, но это самое удачное из того что я придумал.
Итог:
Скорость фильтра меня радует, сейчас это примерно 50-80 миллисекунд при 70 000 изображений. Если что-то еще интересно по проекту, пожалуйста спрашивайте, я буду рад рассказать. Опять же сам проект: http://picsfab.com
Автор: p0is0n