parser_version7

Форк
0
/
osnovaTG.py 
236 строк · 11.2 Кб
1
import asyncio
2
from aiogram import Bot, Dispatcher, types
3
from aiogram.types import Message
4
from aiogram.fsm.storage.memory import MemoryStorage
5
from aiogram.fsm.context import FSMContext
6
from aiogram.filters import Command
7
from aiogram.fsm.state import StatesGroup, State
8
from datetime import date, timedelta
9
from test2 import parse_and_save
10
import mysql.connector
11
import hashlib
12

13
# Замените на ваш токен и ID группы
14
TOKEN = "7032031280:AAEjXQh-WNlqfY2el6a7cj0PtUvJNh-vLM0"
15
GROUP_ID = "-1002448868558"  # Для теста
16

17
# Ключевые слова для поиска
18
keywords = [
19
    "обыски", "задержан", "досудебное расследование", "уголовный процесс", "уголовное дело", "обвинение",
20
    "привлечение к уголовной ответственности", "экономическое преступление", "корпоративное мошенничество",
21
    "уклонение от уплаты налогов", "легализация доходов", "отмывание доходов", "хищение", "вымогательство",
22
    "судебное рассмотрение", "подача апелляции", "кассационная жалоба", "арест имущества", "налоговый аудит",
23
    "налоговая проверка", "налоговое правонарушение", "налоговый спор", "отмывание доходов", 
24
    "открытие дела о банкротстве", "заявление о несостоятельности", "признаки неплатежеспособности", 
25
    "реструктуризация долгов", "ликвидация компании", "арбитражное разбирательство", "введение конкурсного производства", 
26
    "требования кредиторов", "мировое соглашение", "корпоративный спор"
27
]
28

29
# Инициализация бота и диспетчера
30
bot = Bot(token=TOKEN, timeout=60)
31
storage = MemoryStorage()
32
dp = Dispatcher(storage=storage)
33

34
# Конфигурация базы данных
35
config = {
36
    'user': 'root',
37
    'password': 'Uz94deco!',
38
    'host': '127.0.0.1',
39
    'database': 'parser'
40
}
41

42
# Класс для состояний FSM
43
class DaysForm(StatesGroup):
44
    waiting_for_days = State()
45

46
# Функция для нормализации текста сообщения
47
def normalize_text(text):
48
    return ' '.join(text.strip().split()).lower()  # Убираем лишние пробелы и приводим текст к нижнему регистру
49

50
# Функция для вычисления хеша текста сообщения
51
def get_text_hash(text):
52
    normalized_text = normalize_text(text)
53
    return hashlib.sha256(normalized_text.encode('utf-8')).hexdigest()
54

55
# Функция для получения истории сообщений группы (до 1000 сообщений)
56
async def get_group_messages(limit=1000):
57
    all_messages = []
58
    all_hashes = []
59
    try:
60
        offset_message_id = None  # ID последнего полученного сообщения для смещения
61

62
        while len(all_messages) < limit:
63
            # Получаем 100 сообщений с возможным смещением
64
            messages = await bot.get_chat_history(chat_id=GROUP_ID, limit=100, offset_message_id=offset_message_id)
65
            
66
            if not messages:
67
                break  # Если сообщений больше нет, выходим из цикла
68
            
69
            for message in messages:
70
                if message.text:
71
                    normalized_message = normalize_text(message.text)
72
                    all_messages.append(normalized_message)
73
                    all_hashes.append(get_text_hash(normalized_message))
74
            
75
            # Устанавливаем ID последнего сообщения для следующего смещения
76
            offset_message_id = messages[-1].message_id
77
        
78
        # Ограничиваем общее количество сообщений до запрашиваемого лимита
79
        return all_messages[:limit], all_hashes[:limit]
80
    
81
    except Exception as e:
82
        print(f"Ошибка при получении истории сообщений группы: {e}")
83
        return [], []
84

85
# Проверка наличия дубликатов по хешам сообщений в группе или базе данных
86
async def is_duplicate(post_text, group_messages_hashes, conn):
87
    post_text_hash = get_text_hash(post_text)
88

89
    # Проверка на дубликат в истории сообщений группы
90
    if post_text_hash in group_messages_hashes:
91
        return True
92

93
    # Проверка на дубликат в базе данных
94
    cursor = conn.cursor()
95
    cursor.execute("SELECT COUNT(*) FROM sent_posts WHERE post_hash = %s", (post_text_hash,))
96
    count = cursor.fetchone()[0]
97
    cursor.close()
98

99
    return count > 0
100

101
# Ограничиваем скорость запросов, чтобы избежать лимитов
102
async def send_message_with_delay(text, conn):
103
    try:
104
        await bot.send_message(GROUP_ID, text)
105

106
        # Сохраняем хеш отправленного сообщения в базе данных
107
        post_text_hash = get_text_hash(text)
108
        cursor = conn.cursor()
109
        cursor.execute("INSERT INTO sent_posts (post_hash) VALUES (%s)", (post_text_hash,))
110
        conn.commit()
111
        cursor.close()
112

113
        await asyncio.sleep(5)  # Задержка между запросами, чтобы избежать лимита
114
    except Exception as e:
115
        print(f"Ошибка при отправке сообщения: {e}")
116

117
# Функция отправки уникальных постов
118
async def send_unique_posts():
119
    try:
120
        conn = mysql.connector.connect(**config)
121
        cursor = conn.cursor(dictionary=True)
122
        cursor.execute("SELECT post_text, time, channel_name FROM posts")  # Добавили post_date и channel_name
123
        posts = cursor.fetchall()
124

125
        # Получаем до 1000 сообщений из группы и их хеши
126
        group_messages, group_messages_hashes = await get_group_messages(1000)
127

128
        for post in posts:
129
            post_text = post['post_text']
130
            time = post['time'].strftime('%d-%m-%Y')
131
            channel_name = post['channel_name']
132
            
133
            # Перебираем все ключевые слова
134
            for keyword in keywords:
135
                if keyword.lower() in post_text.lower():
136
                    formatted_message = f"Канал: {channel_name}\nДата: {time}\nКлючевое слово: {keyword}\n\n{post_text}"
137

138
                    is_dup = await is_duplicate(formatted_message, group_messages_hashes, conn)
139

140
                    if not is_dup:
141
                        await send_message_with_delay(formatted_message, conn)
142
                        print(f"Отправлен уникальный пост: {formatted_message}")
143
                    else:
144
                        print(f"Пост пропущен (дубликат): {formatted_message}")
145

146
    except Exception as e:
147
        print(f"Ошибка при отправке уникальных постов: {e}")
148
    finally:
149
        cursor.close()
150
        conn.close()
151

152
# Загрузка ссылок и ключевых слов из файлов
153
def load_links_and_keywords():
154
    try:
155
        with open('Links.txt', 'r', encoding='utf-8') as f:
156
            links = [line.strip() for line in f.readlines()]
157
        with open('keywords.txt', 'r', encoding='utf-8') as f:
158
            keywords = [line.strip() for line in f.readlines()]
159
        return links, keywords
160
    except Exception as e:
161
        print(f"Ошибка при загрузке ссылок или ключевых слов: {e}")
162
        return [], []
163

164
# Загрузка количества дней из файла
165
def load_days():
166
    try:
167
        with open('days.txt', 'r') as f:
168
            return int(f.read().strip())
169
    except Exception as e:
170
        print(f"Ошибка при загрузке дней: {e}")
171
        return 7  # Значение по умолчанию
172

173
# Сохранение количества дней в файл
174
def save_days(days):
175
    try:
176
        with open('days.txt', 'w') as f:
177
            f.write(str(days))
178
    except Exception as e:
179
        print(f"Ошибка при сохранении дней: {e}")
180

181
# Фоновая задача для парсинга каждые 15 минут
182
async def scheduled_parsing():
183
    while True:
184
        try:
185
            days = load_days()  # Загружаем количество дней из файла
186
            links, keywords = load_links_and_keywords()
187
            nazvanie = ["Бойлерная", "Кремлёвский безБашенник", "Силовики", "НЕЗЫГАРЬ", "ОПЕР Слил", "SHOT", "Mash", "Baza", "ВЧК-ОГПУ", "КОНТЕКСТ"]  # Названия каналов
188

189
            start_date = date.today() - timedelta(days=days)
190
            
191
            # Асинхронный запуск парсинга
192
            await asyncio.to_thread(parse_and_save, links, nazvanie, keywords, start_date)
193

194
            # Отправка уникальных постов
195
            await send_unique_posts()
196

197
        except Exception as e:
198
            print(f"Ошибка в фоновом парсинге: {e}")
199
        
200
        await asyncio.sleep(900)  # Повтор каждые 15 минут
201

202
# Команда /start
203
@dp.message(Command("start"))
204
async def start_command(message: Message, state: FSMContext):
205
    await message.answer("""Здравствуйте, вас привествует бот по Парсеру данных из разных каналов.
206
    Основные команды в боте:
207
    
208
    /start - запуск бота.
209
    /change_days - изменить время для парсера данных.""")
210
    await message.answer("Сколько дней вы хотите парсить данные?")
211
    await state.set_state(DaysForm.waiting_for_days)
212

213
# Команда для изменения количества дней
214
@dp.message(Command("change_days"))
215
async def change_days(message: Message, state: FSMContext):
216
    await message.answer("Введите количество дней для парсинга:")
217
    await state.set_state(DaysForm.waiting_for_days)
218

219
# Обработка ответа на вопрос о днях
220
@dp.message(DaysForm.waiting_for_days)
221
async def process_days(message: Message, state: FSMContext):
222
    try:
223
        days = int(message.text)
224
        save_days(days)  # Сохраняем количество дней в файл
225
        await message.answer(f"Количество дней успешно изменено на {days}.")
226
    except ValueError:
227
        await message.answer("Пожалуйста, введите число.")
228
    await state.clear()
229

230
# Запуск фона
231
async def on_startup():
232
    asyncio.create_task(scheduled_parsing())
233

234
if __name__ == "__main__":
235
    dp.startup.register(on_startup)
236
    dp.run_polling(bot)
237

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.