бот поиска фраз на компьютере
Я понял, что нужно создать алгоритм, который:
Начинает поиск с рабочего стола (предполагаем, что это папка на компьютере, например, C:\Users\YourUser\Desktop на Windows).
Рекурсивно сканирует папки и подпапки в поисках файлов с расширением .txt.
Ищет уникальные фразы (я предполагаю, что под "фразами" имеются в виду предложения или строки текста, которые содержат введённую пользователем фразу — для простоты возьмём предложения, заканчивающиеся точкой, вопросительным или восклицательным знаком).
Собирает до 40 уникальных таких фраз (уникальность = отсутствие дубликатов в результатах).
Из найденных выводит случайно выбранные 3 фразы (или первые, если случайный выбор не нужен).
Я придумал простой и эффективный алгоритм на основе рекурсивного обхода файловой системы и обработки текста. Он не требует сложных библиотек, но для реализации на Python можно использовать встроенные модули вроде os и random. Вот пошаговое описание алгоритма:
Шаги алгоритма:
Получение ввода от пользователя: Запросить у пользователя фразу для поиска (например, через консоль или GUI). Пусть это будет строка search_phrase.
Определение стартовой папки: Установить путь к рабочему столу. На Windows это обычно os.path.expanduser("~/Desktop") (в Python). Если на другой ОС, адаптировать (например, /home/user/Desktop на Linux).
Рекурсивный обход папок:
Использовать функцию, которая обходит все подпапки (например, с помощью os.walk() в Python).
Для каждого файла проверить, заканчивается ли он на .txt (игнорируя регистр).
Если да, открыть файл и прочитать его содержимое как текст (предполагаем кодировку UTF-8 для поддержки русского языка).
Обработка текста файла:
Разделить текст на предложения (по символам ., !, ? — использовать регулярные выражения для точности, например, re.split(r'[.!?]', text)).
Для каждого предложения проверить, содержит ли оно search_phrase (игнорируя регистр, например, search_phrase.lower() in sentence.lower()).
Если содержит, добавить предложение в множество (set) для обеспечения уникальности. Продолжать до тех пор, пока не наберётся 40 уникальных фраз или не закончатся файлы.
Вывод результатов:
Если найдено менее 40 фраз, вывести все.
Из найденных выбрать 3 случайные фразы (используя случайный выбор) и вывести их.
Если фраз меньше 3, вывести все найденные.
Обработка ошибок: Игнорировать файлы, которые нельзя открыть (например, из-за прав доступа), и продолжить поиск.
Этот алгоритм эффективен для небольших объёмов данных (тысячи файлов), но для очень больших папок может быть медленным — в этом случае можно добавить многопоточность.
Пример реализации на Python
Вот простой скрипт на Python, который реализует этот алгоритм. Сохрани его как .py файл на рабочем столе и запусти (нужен Python 3.x). Он использует только встроенные модули
import os
import re
import random
def find_unique_phrases(search_phrase, start_path, max_phrases=40):
unique_phrases = set()
# Рекурсивный обход папок
for root, dirs, files in os.walk(start_path):
for file in files:
if file.lower().endswith('.txt'):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
text = f.read()
# Разделить на предложения
sentences = re.split(r'[.!?]', text)
for sentence in sentences:
sentence = sentence.strip()
if sentence and search_phrase.lower() in sentence.lower():
unique_phrases.add(sentence)
if len(unique_phrases) >= max_phrases:
break # Прекратить, если набрали 40
if len(unique_phrases) >= max_phrases:
break
except Exception as e:
print(f"Ошибка при чтении {file_path}: {e}")
if len(unique_phrases) >= max_phrases:
break
return list(unique_phrases)
# Основная часть
if __name__ == "__main__":
search_phrase = input("Введите фразу для поиска: ")
desktop_path = os.path.expanduser("~/Desktop") # Адаптировать под ОС, если нужно
phrases = find_unique_phrases(search_phrase, desktop_path)
if not phrases:
print("Фразы не найдены.")
else:
# Выбрать 3 случайные (или первые, если меньше)
selected = random.sample(phrases, min(3, len(phrases)))
print("Найденные фразы:")
for phrase in selected:
print(f"- {phrase}")
Как использовать:
Запусти скрипт.
Введи фразу (например, "привет")
Программа просканирует все .txt файлы на рабочем столе и подпапках,
найдёт до 40 уникальных предложений с этой фразой и выведет 3 случайные.
Если нужно доработать (например, сделать GUI, добавить фильтры или оптимизировать), дай знать — я могу помочь! Если это не то, что имел в виду, уточни детали.
ищем фразы которые на 10-20% похожи на фразу ввода
Обновлённый алгоритм поиска похожих фраз в текстовых файлах
Я понял, что нужно изменить поиск: вместо точного совпадения подстроки теперь ищем фразы (предложения), которые похожи на введённую фразу на 10-20%. Это добавляет интересный поворот — теперь это не точный матч, а семантическая/лексическая схожесть.
Что значит "10-20% похожести"?
Это субъективно, поэтому я выбрал простую и надёжную метрику: Jaccard similarity (коэффициент Жаккара) на основе слов.
Разбиваем вводную фразу и каждое предложение на уникальные слова (игнорируя регистр и знаки препинания).
Jaccard = (количество общих слов) / (количество уникальных слов в объединении двух множеств).
Если Jaccard в диапазоне [0.1, 0.2] (т.е. 10-20%), то считаем фразу похожей.
Почему Jaccard? Он простой, не требует внешних библиотек и хорошо работает для коротких текстов. Если нужно что-то посложнее (например, расстояние Левенштейна или эмбеддинги с ИИ), дай знать — но это усложнит код.
Уникальность по-прежнему через set (по тексту предложения).
Остальное остаётся: сканируем .txt на рабочем столе и подпапках, собираем до 40 уникальных, выводим 3 случайные.
Обновлённые шаги алгоритма:
Получение ввода: Запросить фразу для поиска.
Подготовка вводной фразы: Разбить на слова, очистить от знаков препинания, привести к нижнему регистру, взять уникальные слова в set.
Рекурсивный обход: Как раньше, с os.walk().
Обработка текста:
Разделить на предложения (по . ! ?).
Для каждого предложения: разбить на слова, вычислить Jaccard с вводной фразой.
Если 0.1 ; Jaccard ; 0.2 и предложение не пустое, добавить в set уникальных фраз.
Остановить на 40 уникальных.
Вывод: 3 случайные из найденных.
Обработка ошибок: Как раньше.
Этот подход найдёт фразы, которые делят 10-20% слов с вводной (например, если ввод "красный дом в лесу", то подойдут предложения вроде "зелёный лес полон тайн" — если пересечение ~15%).
Обновлённый пример реализации на Python
Вот доработанный скрипт. Я добавил функцию для Jaccard без доп. библиотек. Сохрани как .py и запусти.
import os
import re
import random
import string
def jaccard_similarity(set1, set2):
"""Вычисляет Jaccard similarity между двумя множествами слов."""
if not set1 or not set2:
return 0.0
intersection = len(set1.intersection(set2))
union = len(set1.union(set2))
return intersection / union if union > 0 else 0.0
def clean_words(text):
"""Очищает текст от знаков препинания и приводит к нижнему регистру."""
translator = str.maketrans('', '', string.punctuation)
words = re.findall(r'\b\w+\b', text.lower().translate(translator))
return set(words) # Уникальные слова
def find_similar_phrases(search_phrase, start_path, min_sim=0.1, max_sim=0.2, max_phrases=40):
search_words = clean_words(search_phrase)
if not search_words:
print("Вводная фраза не содержит слов для поиска.")
return []
unique_phrases = set()
# Рекурсивный обход папок
for root, dirs, files in os.walk(start_path):
for file in files:
if file.lower().endswith('.txt'):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
text = f.read()
# Разделить на предложения
sentences = re.split(r'[.!?]+', text)
for sentence in sentences:
sentence = sentence.strip()
if len(sentence) > 10: # Игнорируем слишком короткие
sentence_words = clean_words(sentence)
similarity = jaccard_similarity(search_words, sentence_words)
if min_sim <= similarity <= max_sim:
unique_phrases.add(sentence)
if len(unique_phrases) >= max_phrases:
break # Прекратить, если набрали 40
if len(unique_phrases) >= max_phrases:
break
except Exception as e:
print(f"Ошибка при чтении {file_path}: {e}")
if len(unique_phrases) >= max_phrases:
break
return list(unique_phrases)
# Основная часть
if __name__ == "__main__":
search_phrase = input("Введите фразу для поиска (похожести 10-20%): ")
desktop_path = os.path.expanduser("~/Desktop") # Адаптировать под ОС, если нужно
phrases = find_similar_phrases(search_phrase, desktop_path)
if not phrases:
print("Похожие фразы не найдены.")
else:
print(f"Найдено {len(phrases)} похожих фраз (10-20% сходства).")
# Выбрать 3 случайные (или все, если меньше)
selected = random.sample(phrases, min(3, len(phrases)))
print("Выбранные примеры:")
for phrase in selected:
print(f"- {phrase}")
Как использовать:
Запусти скрипт.
Введи фразу (например, "солнечный день в парке").
Программа найдёт предложения, где ~10-20% слов совпадают (например, "дождливый вечер у реки" может подойти, если пересечение "день/в/парке" ~15%).
Вывод: 3 случайные из до 40 найденных.
Возможные улучшения:
Точность схожести: Если Jaccard не подходит, можно использовать расстояние Левенштейна (для символов) — добавлю, если скажешь.
Минимум длины: Добавил фильтр на предложения >10 символов, чтобы избежать мусора.
Процент: Если "10-20%" имел в виду что-то другое (например, по символам или семантике с ИИ), уточни — могу интегрировать библиотеку вроде difflib (встроенная) или даже Hugging Face для эмбеддингов.
Тестирование: Создай тестовые .txt файлы на столе, чтобы проверить.
import os
import re
import random
import string
def jaccard_similarity(set1, set2):
"""Вычисляет Jaccard similarity между двумя множествами слов."""
if not set1 or not set2:
return 0.0
intersection = len(set1.intersection(set2))
union = len(set1.union(set2))
return intersection / union if union > 0 else 0.0
def clean_words(text):
"""Очищает текст от знаков препинания и приводит к нижнему регистру."""
translator = str.maketrans('', '', string.punctuation)
words = re.findall(r'\b\w+\b', text.lower().translate(translator))
return set(words) # Уникальные слова
def find_similar_phrases(search_phrase, start_path, min_sim=0.1, max_sim=0.2, max_phrases=40):
search_words = clean_words(search_phrase)
if not search_words:
print("Вводная фраза не содержит слов для поиска.")
return []
unique_phrases = set()
# Рекурсивный обход папок
for root, dirs, files in os.walk(start_path):
for file in files:
if file.lower().endswith('.txt'):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
text = f.read()
# Разделить на предложения
sentences = re.split(r'[.!?]+', text)
for sentence in sentences:
sentence = sentence.strip()
if len(sentence) > 10: # Игнорируем слишком короткие
sentence_words = clean_words(sentence)
similarity = jaccard_similarity(search_words, sentence_words)
if min_sim <= similarity <= max_sim:
unique_phrases.add(sentence)
if len(unique_phrases) >= max_phrases:
break # Прекратить, если набрали 40
if len(unique_phrases) >= max_phrases:
break
except Exception as e:
print(f"Ошибка при чтении {file_path}: {e}")
if len(unique_phrases) >= max_phrases:
break
return list(unique_phrases)
# Основная часть
if __name__ == "__main__":
search_phrase = input("поиск: ")
desktop_path = os.path.expanduser("~/Desktop") # Адаптировать под ОС, если нужно
phrases = find_similar_phrases(search_phrase, desktop_path)
if not phrases:
print("Похожие фразы не найдены.")
else:
print(f"Найдено {len(phrases)} похожих фраз (10-20% сходства).")
# Выбрать 3 случайные (или все, если меньше)
selected = random.sample(phrases, min(3, len(phrases)))
print("Выбранные примеры:")
for phrase in selected:
print(f"- {phrase}")
ред. edit **
import os
import re
import random
import string
def jaccard_similarity(set1, set2):
"""Вычисляет Jaccard similarity между двумя множествами слов."""
if not set1 or not set2:
return 0.0
intersection = len(set1.intersection(set2))
union = len(set1.union(set2))
return intersection / union if union > 0 else 0.0
def clean_words(text):
"""Очищает текст от знаков препинания и приводит к нижнему регистру."""
translator = str.maketrans('', '', string.punctuation)
words = re.findall(r'\b\w+\b', text.lower().translate(translator))
return set(words) # Уникальные слова
def find_similar_phrases(search_phrase, start_path, min_sim=0.1, max_sim=0.2, max_phrases=40):
search_words = clean_words(search_phrase)
if not search_words:
return []
unique_phrases = set()
# Рекурсивный обход папок
for root, dirs, files in os.walk(start_path):
for file in files:
if file.lower().endswith('.txt'):
file_path = os.path.join(root, file)
text = None
try:
with open(file_path, 'r', encoding='utf-8') as f:
text = f.read()
except UnicodeDecodeError:
try:
with open(file_path, 'r', encoding='cp1251') as f: # Попытка с Windows-1251
text = f.read()
except UnicodeDecodeError:
continue # Пропустить файл, если не удаётся прочитать
if text:
# Разделить на предложения
sentences = re.split(r'[.!?]+', text)
for sentence in sentences:
sentence = sentence.strip()
if len(sentence) > 10: # Игнорируем слишком короткие
sentence_words = clean_words(sentence)
similarity = jaccard_similarity(search_words, sentence_words)
if min_sim <= similarity <= max_sim:
unique_phrases.add(sentence)
if len(unique_phrases) >= max_phrases:
break
if len(unique_phrases) >= max_phrases:
break
if len(unique_phrases) >= max_phrases:
break
return list(unique_phrases)
# Основная часть с упрощённым циклом
if __name__ == "__main__":
desktop_path = os.path.expanduser("~/Desktop")
while True:
search_phrase = input("поиск: ")
phrases = find_similar_phrases(search_phrase, desktop_path)
if phrases:
# Выбрать 3 случайные (или все, если меньше)
selected = random.sample(phrases, min(3, len(phrases)))
for phrase in selected:
print(phrase)
# Иначе ничего не выводим, просто ждём следующий ввод
Свидетельство о публикации №125101400965