Telegram User-бот для парсинга группы: сбор данных и аналитика
Telegram User-боты отлично подходят для парсинга (сбора данных) из Telegram-групп и каналов. В отличие от обычных ботов, user-боты могут читать все сообщения в группах, собирать статистику участников и анализировать активность.Зачем нужен парсинг групп?
1. Сбор статистики и аналитики
- Подсчет количества сообщений от каждого участника
- Анализ активности группы по времени
- Сбор метрик популярности контента
- Отслеживание роста участников
2. Мониторинг контента
- Сбор всех сообщений из группы
- Поиск сообщений по ключевым словам
- Экспорт истории группы
- Анализ типов контента (текст, медиа, ссылки)
3. Исследование и анализ
- Изучение поведения участников
- Анализ популярных тем обсуждений
- Сбор данных для исследований
- Мониторинг конкурентов
Что мы создадим?
В этом руководстве мы создадим User-бота для парсинга Telegram-группы, который будет выполнять следующие задачи: Задачи бота:- Собирать все сообщения из группы с сохранением в базу данных
- Собирать информацию об участниках группы
- Подсчитывать статистику активности каждого участника
- Экспортировать данные в CSV и JSON форматы
- Фильтровать сообщения по ключевым словам
- Собирать медиа-файлы из группы
Шаг 1: Получение API credentials
Для работы User-бота нужны API credentials от Telegram. Если вы еще не получили их, сделайте следующее:- Перейдите на https://my.telegram.org/
- Авторизуйтесь своим номером телефона
- Перейдите в раздел "API development tools"
- Создайте новое приложение
- Сохраните
api_idиapi_hash
Шаг 2: Установка библиотек
Для нашего бота парсера понадобятся следующие библиотеки:pip install telethon pandastelethon— для работы с Telegram APIpandas— для работы с данными и экспорта в CSV
Шаг 3: Создание базы данных
Создайте файлdatabase.py для работы с базой данных:
import sqlite3
from datetime import datetime
class Database:
def __init__(self, db_name='group_parser.db'):
self.conn = sqlite3.connect(db_name)
self.create_tables()
def create_tables(self):
cursor = self.conn.cursor()
# Таблица участников
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
user_id INTEGER UNIQUE,
username TEXT,
first_name TEXT,
last_name TEXT,
phone TEXT,
is_bot INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
# Таблица сообщений
cursor.execute('''
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
message_id INTEGER,
user_id INTEGER,
chat_id INTEGER,
text TEXT,
date TIMESTAMP,
is_reply INTEGER DEFAULT 0,
reply_to_message_id INTEGER,
media_type TEXT,
media_file_id TEXT,
views INTEGER DEFAULT 0,
forwards INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (user_id)
)
''')
# Таблица статистики
cursor.execute('''
CREATE TABLE IF NOT EXISTS statistics (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
total_messages INTEGER DEFAULT 0,
total_media INTEGER DEFAULT 0,
total_links INTEGER DEFAULT 0,
last_activity TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (user_id)
)
''')
self.conn.commit()
def add_user(self, user_id, username=None, first_name=None, last_name=None, phone=None, is_bot=False):
cursor = self.conn.cursor()
cursor.execute('''
INSERT OR REPLACE INTO users (user_id, username, first_name, last_name, phone, is_bot)
VALUES (?, ?, ?, ?, ?, ?)
''', (user_id, username, first_name, last_name, phone, is_bot))
self.conn.commit()
def add_message(self, message_id, user_id, chat_id, text, date, is_reply=False, reply_to=None, media_type=None, media_file_id=None, views=0, forwards=0):
cursor = self.conn.cursor()
cursor.execute('''
INSERT INTO messages (message_id, user_id, chat_id, text, date, is_reply, reply_to_message_id, media_type, media_file_id, views, forwards)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (message_id, user_id, chat_id, text, date, is_reply, reply_to, media_type, media_file_id, views, forwards))
self.conn.commit()
def update_statistics(self, user_id, total_messages=0, total_media=0, total_links=0):
cursor = self.conn.cursor()
cursor.execute('''
INSERT OR REPLACE INTO statistics (user_id, total_messages, total_media, total_links, last_activity)
VALUES (?,
COALESCE((SELECT total_messages FROM statistics WHERE user_id = ?), 0) + ?,
COALESCE((SELECT total_media FROM statistics WHERE user_id = ?), 0) + ?,
COALESCE((SELECT total_links FROM statistics WHERE user_id = ?), 0) + ?,
CURRENT_TIMESTAMP
)
''', (user_id, user_id, total_messages, user_id, total_media, user_id, total_links))
self.conn.commit()
def get_all_messages(self):
cursor = self.conn.cursor()
cursor.execute('''
SELECT m.*, u.username, u.first_name
FROM messages m
LEFT JOIN users u ON m.user_id = u.user_id
ORDER BY m.date DESC
''')
return cursor.fetchall()
def get_user_statistics(self):
cursor = self.conn.cursor()
cursor.execute('''
SELECT u.user_id, u.username, u.first_name,
s.total_messages, s.total_media, s.total_links, s.last_activity
FROM statistics s
JOIN users u ON s.user_id = u.user_id
ORDER BY s.total_messages DESC
''')
return cursor.fetchall()
def close(self):
self.conn.close()Шаг 4: Создание парсера
Создайте файлgroup_parser_bot.py:
from telethon import TelegramClient, events
import asyncio
import os
from datetime import datetime
import re
from database import Database
Данные из my.telegram.org
API_ID = 12345678 # Замените на ваш api_id
API_HASH = 'your_api_hash_here' # Замените на ваш api_hash
ID группы для парсинга (можно получить через @userinfobot)
GROUP_ID = -1001234567890 # Замените на ID вашей группы
Создаем клиент
client = TelegramClient('parser_bot_session', API_ID, API_HASH)
Инициализируем базу данных
db = Database('parsed_group.db')
Счетчики для статистики
stats = {
'messages_parsed': 0,
'users_found': 0,
'media_files': 0,
'links_found': 0
}
Функция для извлечения ссылок из текста
def extract_links(text):
if not text:
return []
url_pattern = r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
return re.findall(url_pattern, text)
Функция для определения типа медиа
def get_media_type(message):
if message.photo:
return 'photo'
elif message.video:
return 'video'
elif message.document:
return 'document'
elif message.audio:
return 'audio'
elif message.voice:
return 'voice'
elif message.sticker:
return 'sticker'
elif message.gif:
return 'gif'
return None
Обработчик новых сообщений в группе
@client.on(events.NewMessage(chats=GROUP_ID))
async def parse_message(event):
message = event.message
sender = await event.get_sender()
# Сохраняем информацию об участнике
if sender:
db.add_user(
user_id=sender.id,
username=sender.username,
first_name=sender.first_name,
last_name=sender.last_name,
phone=getattr(sender, 'phone', None),
is_bot=getattr(sender, 'bot', False)
)
stats['users_found'] += 1
# Извлекаем данные из сообщения
text = message.text or message.raw_text or ''
message_id = message.id
date = message.date
is_reply = message.reply_to is not None
reply_to_id = message.reply_to.reply_to_msg_id if is_reply else None
# Определяем тип медиа
media_type = get_media_type(message)
media_file_id = None
if media_type:
stats['media_files'] += 1
if message.photo:
media_file_id = message.photo.id
elif hasattr(message, 'file') and message.file:
media_file_id = message.file.id
# Извлекаем ссылки
links = extract_links(text)
links_count = len(links)
stats['links_found'] += links_count
# Получаем статистику просмотров и пересылок
views = getattr(message, 'views', 0) or 0
forwards = getattr(message, 'forwards', 0) or 0
# Сохраняем сообщение в базу
db.add_message(
message_id=message_id,
user_id=sender.id if sender else 0,
chat_id=GROUP_ID,
text=text,
date=date,
is_reply=is_reply,
reply_to=reply_to_id,
media_type=media_type,
media_file_id=media_file_id,
views=views,
forwards=forwards
)
# Обновляем статистику участника
if sender:
db.update_statistics(
user_id=sender.id,
total_messages=1,
total_media=1 if media_type else 0,
total_links=links_count
)
stats['messages_parsed'] += 1
# Выводим прогресс каждые 100 сообщений
if stats['messages_parsed'] % 100 == 0:
print(f"📊 Обработано сообщений: {stats['messages_parsed']}")
print(f"👥 Участников: {stats['users_found']}")
print(f"📎 Медиа-файлов: {stats['media_files']}")
print(f"🔗 Ссылок: {stats['links_found']}")
print("---")
Функция для парсинга истории группы (все сообщения)
async def parse_group_history():
"""Парсит всю историю группы с самого начала"""
print(f"🔄 Начинаю парсинг истории группы {GROUP_ID}...")
try:
messages_count = 0
async for message in client.iter_messages(GROUP_ID, limit=None):
# Обрабатываем сообщение через наш обработчик
event = type('Event', (), {
'message': message,
'get_sender': lambda: client.get_entity(message.sender_id) if message.sender_id else None
})()
# Имитируем событие для обработчика
sender = await event.get_sender() if message.sender_id else None
# Сохраняем участника
if sender:
db.add_user(
user_id=sender.id,
username=sender.username,
first_name=sender.first_name,
last_name=sender.last_name,
phone=getattr(sender, 'phone', None),
is_bot=getattr(sender, 'bot', False)
)
# Извлекаем данные
text = message.text or message.raw_text or ''
media_type = get_media_type(message)
links = extract_links(text)
# Сохраняем сообщение
db.add_message(
message_id=message.id,
user_id=sender.id if sender else 0,
chat_id=GROUP_ID,
text=text,
date=message.date,
is_reply=message.reply_to is not None,
reply_to=message.reply_to.reply_to_msg_id if message.reply_to else None,
media_type=media_type,
media_file_id=None,
views=getattr(message, 'views', 0) or 0,
forwards=getattr(message, 'forwards', 0) or 0
)
# Обновляем статистику
if sender:
db.update_statistics(
user_id=sender.id,
total_messages=1,
total_media=1 if media_type else 0,
total_links=len(links)
)
messages_count += 1
if messages_count % 100 == 0:
print(f"✅ Обработано сообщений из истории: {messages_count}")
print(f"✨ Парсинг завершен! Всего обработано: {messages_count} сообщений")
except Exception as e:
print(f"❌ Ошибка при парсинге истории: {e}")
Функция экспорта данных
def export_to_csv():
"""Экспортирует данные в CSV файлы"""
import csv
from datetime import datetime
# Экспорт сообщений
messages = db.get_all_messages()
with open(f'messages_export_{datetime.now().strftime("%Y%m%d_%H%M%S")}.csv', 'w', encoding='utf-8', newline='') as f:
writer = csv.writer(f)
writer.writerow(['ID', 'Message ID', 'User ID', 'Username', 'First Name', 'Text', 'Date', 'Media Type', 'Views', 'Forwards'])
for msg in messages:
writer.writerow(msg)
# Экспорт статистики
stats_data = db.get_user_statistics()
with open(f'statistics_export_{datetime.now().strftime("%Y%m%d_%H%M%S")}.csv', 'w', encoding='utf-8', newline='') as f:
writer = csv.writer(f)
writer.writerow(['User ID', 'Username', 'First Name', 'Total Messages', 'Total Media', 'Total Links', 'Last Activity'])
for stat in stats_data:
writer.writerow(stat)
print("📁 Данные экспортированы в CSV файлы")
Запуск бота
async def main():
await client.start()
print("🤖 Бот-парсер запущен!")
print(f"📊 Парсинг группы: {GROUP_ID}")
print("\nВыберите режим работы:")
print("1. Парсинг только новых сообщений (режим реального времени)")
print("2. Парсинг всей истории группы")
print("3. Экспорт данных в CSV")
# В реальном приложении можно добавить интерактивный выбор
# Для примера запускаем парсинг истории
choice = input("\nВведите номер (1-3): ").strip()
if choice == '1':
print("🔄 Режим реального времени активирован. Ожидаю новые сообщения...")
await client.run_until_disconnected()
elif choice == '2':
await parse_group_history()
export_to_csv()
elif choice == '3':
export_to_csv()
else:
print("Неверный выбор. Запускаю режим реального времени...")
await client.run_until_disconnected()
db.close()
if __name__ == '__main__':
asyncio.run(main())Шаг 5: Дополнительные функции
Фильтрация сообщений по ключевым словам
Добавьте в обработчик сообщений:# Ключевые слова для фильтрации
KEYWORDS = ['важное', 'новости', 'объявление']
В функции parse_message после сохранения сообщения:
if any(keyword.lower() in text.lower() for keyword in KEYWORDS):
print(f"🔔 Найдено сообщение с ключевым словом: {text[:100]}")
# Можно отправить уведомление или сохранить в отдельную таблицуСбор участников группы
Добавьте функцию для получения списка всех участников:async def collect_group_members():
"""Собирает информацию обо всех участниках группы"""
print("👥 Собираю список участников группы...")
participants = []
async for user in client.iter_participants(GROUP_ID):
db.add_user(
user_id=user.id,
username=user.username,
first_name=user.first_name,
last_name=user.last_name,
phone=getattr(user, 'phone', None),
is_bot=getattr(user, 'bot', False)
)
participants.append({
'id': user.id,
'username': user.username,
'name': f"{user.first_name} {user.last_name or ''}".strip()
})
print(f"✅ Собрано участников: {len(participants)}")
return participantsЭкспорт в JSON
Добавьте функцию экспорта в JSON:import json
def export_to_json():
"""Экспортирует данные в JSON файл"""
messages = db.get_all_messages()
stats = db.get_user_statistics()
data = {
'messages': [
{
'id': msg[0],
'message_id': msg[1],
'user_id': msg[2],
'username': msg[8],
'text': msg[4],
'date': msg[5].isoformat() if msg[5] else None,
'media_type': msg[9]
}
for msg in messages
],
'statistics': [
{
'user_id': stat[0],
'username': stat[1],
'total_messages': stat[3],
'total_media': stat[4],
'total_links': stat[5]
}
for stat in stats
]
}
filename = f'export_{datetime.now().strftime("%Y%m%d_%H%M%S")}.json'
with open(filename, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"📁 Данные экспортированы в {filename}")Безопасность и ограничения
Важные моменты:
- Соблюдайте правила Telegram — не нарушайте Terms of Service
- Уважайте приватность — не распространяйте собранные данные без разрешения
- Соблюдайте лимиты API — добавляйте задержки между запросами
- Храните данные безопасно — шифруйте базу данных при необходимости
Рекомендации:
- Добавьте задержки при парсинге больших групп
- Ограничьте количество запросов в секунду
- Регулярно делайте бэкапы базы данных
- Используйте виртуальное окружение Python
Пример использования
- Запустите бота:
python group_parser_bot.py- Выберите режим парсинга:
- Результаты:
Заключение
User-бот для парсинга групп — это мощный инструмент для сбора и анализа данных из Telegram. Он позволяет автоматизировать процесс сбора информации, анализировать активность участников и экспортировать данные для дальнейшего анализа. Помните о приватности и правилах использования. Используйте парсинг ответственно и только для законных целей.Полезные ресурсы:
2414 просмотров
0 лайков
0 комментариев
Комментарии (0)
Пока нет комментариев. Будьте первым!