parser_version8

Форк
0
/
osnovaTG.py 
237 строк · 11.3 Кб
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 = "-1002263530866"  # Для теста
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
    'charset': 'utf8mb4'
41
}
42

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

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

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

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

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

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

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

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

100
    return count > 0
101

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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