Автоматизированный сбор данных в чатах и рассылка для Telegram на Python

Plane-Network-Application-Social-Internet-Telegram-5952446.jpg


Привет всем!
Это моя первая статья, буду рад за конструктивную критику. В приниципе, любая критика приветствуется)​

UPDATE.
Меня правильно поправили - спам в РФ запрещен. Но есть возможность проводить автоматизированный сбор данных. Поэтому перед использованием данного метода следует получить согласие «каждого субъекта на такие действия».
То же самое с рекламной рассылкой - стоит также получить согласие «каждого субъекта на такие действия».
Федеральный закон о персональных данных

Обычно в этом месте все пишут предысторию, но у меня она достаточно заурядная: недавно возникла необходимость сделать рассылку по телеграм(никакой чёрнухи :Р).
Сначала посмотрел готовые решения. Их действительно очень много, но либо не нравилось, либо не подходило по нуждам, либо я совсем терялся в коде.
Вот решил, наконец, проверить свои навыки после курса «Python для Пентестера» и написать все сам.

Ссылка на готовый код с гитхаб в конце статьи.
У нас будет три основные части программы: коннектор клиента(как это назвать по-русски??), сбор участников чата и рассылка по пользователям.

Будем использовать библиотеку telethon. Документация по библиотеке - Telethon’s Documentation — Telethon 1.24.0 documentation

Устанавливаем библиотеку telethon
Код:
pip3 install telethon
Импортируем необходимые модули:
Python:
import time
import random

from telethon.sync import TelegramClient
from telethon.errors.rpcerrorlist import PeerFloodError, SessionPasswordNeededError

Далее необходимо получить App api_id и App api_hash. Для это заходим на my.telegram.org в раздел API development tools.

2022-04-29_17-10.png


Создаем app, копируем необходимое и создаем переменные:
Код:
phone = 'строка'
api_id = число
api_hash = 'строка'

С помощью следующих двух строчек мы подключаемся к Телеграм
Python:
client = TelegramClient(phone, api_id, api_hash)
client.connect()

Но при первом подключении надо будет ввести одноразовый код, а если включена двухфакторная авторизация, то и дополнительный пароль.
Поэтому пишем такую конструцию, которая учитывает эти вопросы.

Python:
if not сlient.is_user_authorized():
    #запрашиваем однаразовый код
    client.send_code_request(phone)
    try:
        client.sign_in(phone, input('Enter verification code: '))
    #дополнительный пароль двухфакторной авторизации если необходимо
    except SessionPasswordNeededError:
        client.sign_in(password=input("Enter password: "))

В текущей директории создается файл *.session. Был момент, когда я долго разбирался как работает подключение и коннектился огромное количество раз, и Телеграм забанил меня на несколько суток. Если такое случится, нужно удалить это файл сессии и приконнектиться заново.

Получаем список чатов:
Python:
chats = [dialog for dialog in client.get_dialogs() if dialog.is_group and dialog.is_channel]
print('From which chat you want to parse members:')
#выводим список чатов для выбора
[print(str(chats.index(i) + 1) + ' - ' + i.title) for i in chats]

.get_dialogs – получить все диалоги
.is_group - проверка является ли диалог групповым чатом/megagroup-чатом
.is_channel – то же самое для каналов.
То есть вместе два этих условия дают спарсить групповые чаты от каналов(пабликов). Отдельно .is_channel можно спарсить участников канала, только если имеются админские права.

Дальше берем в переменную выбор пользователя.
Python:
your_choice = input(‘Your choice is: ‘)

Собираем пользователей если у них имеется юзернейм
!Можно спарсить только тех, у кого юзернейм не закрыт!
Python:
users = [user.username for user in self.client.get_participants(your_choice ) if user.username]

Можно также спарсить такие параметры как:
id, bot(False or True), scam(False or True), fake(False or True), access_hash, first_name, last_name, phone, и status(когда в последний раз был онлайн)

Далее можно добавить опцию выбора: сохранить или спамить по списку. А можно и не добавлять. Взрослые люди все-таки, сами можете выбрать есть мороженное на завтрак или в обед.

Итак, спам.

Python:
delay = random.randint(15, 40)
- время задержки между собщениями. Лимиты часто меняются и стоит гуглить, чтобы не словить бан.
Лимиты в телеграме на данный момент:
  • Оптимальная пауза при рассылке от 10 сек.
  • На рассылку без ссылки - 40 сообщений.
  • На рассылку со ссылкой - 10 сообщений.

Варианты сообщения можно положить в список message. И мы будем выбирать рандомное сообщение для каждого юзера.
Python:
message = ['Hello!', 'Ola!', 'Ni Hao!']
#сделаю рассылку на первые 40 юзеров из списка
for user in users[:39]:
    print("Sending Message to: ", user)
    try:
        #отправляем сообщение
        client.send_message(user, random.choice(message))
    #Возможно словить Flood Error, поэтому лучше сразу прекратить спам и разорвать связь
    except PeerFloodError:
        print("[!] Got Flood Error from telegram. \n[!] Try later.")
        self.client.disconnect()
        break
    except Exception as e:
        print("[!] Error:", e, "\n Trying to continue...")
        continue
    else:
        if user != users[:39]:
            print(f"Waiting {delay} seconds")
            time.sleep(delay)
print('\nEnd of the program')

Вот и все!
В программу можно добавить красивую заставку, менюшку, colorama, а также обработчики исключений и больше выбора(сохранить, не сохранить, продолжить, сменить аккаунт и тд).
Это уже по Вашему усмотрению.
PJHoqNgRTyBbULPlDHpbw_thumb_462.jpg

Ссылка на GitHub:
 
Последнее редактирование модератором:
Привет. У тебя на самой первой картинке водяной знак от какого-то фотостока. Картинки для статей должны быть под лицензией Creative Commons (разрешены для использования без упоминания автора). В целом статья нормальная, только ты не очень правильно используешь list comprehension (генератор списка). Да и название статьи противоречит законам РФ, нужно сменить на что-то более "безобидное"
 
Последнее редактирование:
  • Нравится
Реакции: Dzen
Привет. У тебя на самой первой картинке водяной знак от какого-то фотостока. Картинки для статей должны быть под лицензией Creative Commons (разрешены для использования без упоминания автора). В целом статья нормальная, только ты не очень правильно используешь list comprehension (генератор списка). Да и название статьи противоречит законам РФ, нужно сменить на что-то более "безобидное"
Привет! Спасибо за поправки.
Где неправильно в list comprehension или что конкретно мне гуглить?
 
Привет! Спасибо за поправки.
Где неправильно в list comprehension или что конкретно мне гуглить?
Вот смотри -
Python:
users = []
[users.append(user.username) for user in self.client.get_participants(your_choice ) if user.username]
У тебя по факту получается объявление пустого списка и цикл в 1 строку. Но в Python можно сразу в объявлении списка делать цикл в одну строку - list comprehension. И код у тебя будет таким:
Python:
users = [user.username for user in self.client.get_participants(your_choice ) if user.username]
 
есть сомнения по поводу
if dialog.is_group and dialog.is_channel
разве может канал быть одновременно и группой?
 
есть сомнения по поводу
if dialog.is_group and dialog.is_channel
разве может канал быть одновременно и группой?
Методом проб и ошибок пришёл к выводу, что с этими условиями выводятся чаты, которые принадлежат каналам
 
Спасибо, интересная статья!
 
Спасибо за статью!
Можешь подсказать, где ты смотришь лимиты сообщений?
 
коннектор клиента(как это назвать по-русски??), сбор участников чата и рассылка по пользователям.
Клиентский коннектор, но лично мне больше нравиться прямой перевод - разъем клиента.)
вообще порой лучше не переводить термины. Connector - Grabber - Sender и всем всё понятно.

в итоге ты бота тестил? сколько сообщений смог разослать до бана?
 
Клиентский коннектор, но лично мне больше нравиться прямой перевод - разъем клиента.)
вообще порой лучше не переводить термины. Connector - Grabber - Sender и всем всё понятно.

в итоге ты бота тестил? сколько сообщений смог разослать до бана?
Да, успешно тестил. 38-40 сообщений в день с одного аккаунта отсылается. Да, немного, но для моей задачи отлично подошло. Пять аккаунтов за пять дней - 1000 сообщений.
Если flood error - удаляю сессию и откладываю аккаунт на день.
 
  • Нравится
Реакции: MLNK
  • Нравится
Реакции: MLNK
Выдает ошибку , ругается на self. Версия telethon 1.24.0 , питон - 3.9.10 .
что только не пробовал - не робит.
Python:
  File "C:\Users\Admin\Desktop\seller + parser\parserbot.py", line 23, in parse
    main(api_id,api_hash,phone)
  File "C:\Users\Admin\Desktop\seller + parser\parserbot.py", line 38, in main
    users = [user.username for user in self.client.get_participants(your_choice ) if user.username]
NameError: name 'self' is not defined
 
Выдает ошибку , ругается на self. Версия telethon 1.24.0 , питон - 3.9.10 .
что только не пробовал - не робит.
Python:
  File "C:\Users\Admin\Desktop\seller + parser\parserbot.py", line 23, in parse
    main(api_id,api_hash,phone)
  File "C:\Users\Admin\Desktop\seller + parser\parserbot.py", line 38, in main
    users = [user.username for user in self.client.get_participants(your_choice ) if user.username]
NameError: name 'self' is not defined
покажите весь код, пожалуйста
 
Все данные (телефон и тд были указаны.)

покажите весь код, пожалуйста
Python:
import time
import random

from telethon.sync import TelegramClient
from telethon.errors.rpcerrorlist import PeerFloodError, SessionPasswordNeededError

phone = 'phone'
api_id = id
api_hash = 'hash'

client = TelegramClient(phone, api_id, api_hash)
client.connect()

if not сlient.is_user_authorized():
    client=Client(phone,api_id,api_hash)
    chats = [dialog for dialog in client.get_dialogs() if dialog.is_group and dialog.is_channel]
print('From which chat you want to parse members:')
#выводим список чатов для выбора
[print(str(chats.index(i) + 1) + ' - ' + i.title) for i in chats]
your_choice = input(‘Your choice is: ‘)
users = [user.username for user in self.client.get_participants(your_choice ) if user.username]
delay = random.randint(15, 40)
message = ['Hello!', 'Ola!', 'Ni Hao!']
#сделаю рассылку на первые 40 юзеров из списка
for user in users[:39]:
    print("Sending Message to: ", user)
    try:
        #отправляем сообщение
        client.send_message(user, random.choice(message))
    #Возможно словить Flood Error, поэтому лучше сразу прекратить спам и разорвать связь
    except PeerFloodError:
        print("[!] Got Flood Error from telegram. \n[!] Try later.")
        self.client.disconnect()
        break
    except Exception as e:
        print("[!] Error:", e, "\n Trying to continue...")
        continue
    else:
        if user != users[:39]:
            print(f"Waiting {delay} seconds")
            time.sleep(delay)
print('\nEnd of the program')
 
Все данные (телефон и тд были указаны.)


Python:
import time
import random

from telethon.sync import TelegramClient
from telethon.errors.rpcerrorlist import PeerFloodError, SessionPasswordNeededError

phone = 'phone'
api_id = id
api_hash = 'hash'

client = TelegramClient(phone, api_id, api_hash)
client.connect()

if not сlient.is_user_authorized():
    client=Client(phone,api_id,api_hash)
    chats = [dialog for dialog in client.get_dialogs() if dialog.is_group and dialog.is_channel]
print('From which chat you want to parse members:')
#выводим список чатов для выбора
[print(str(chats.index(i) + 1) + ' - ' + i.title) for i in chats]
your_choice = input(‘Your choice is: ‘)
users = [user.username for user in self.client.get_participants(your_choice ) if user.username]
delay = random.randint(15, 40)
message = ['Hello!', 'Ola!', 'Ni Hao!']
#сделаю рассылку на первые 40 юзеров из списка
for user in users[:39]:
    print("Sending Message to: ", user)
    try:
        #отправляем сообщение
        client.send_message(user, random.choice(message))
    #Возможно словить Flood Error, поэтому лучше сразу прекратить спам и разорвать связь
    except PeerFloodError:
        print("[!] Got Flood Error from telegram. \n[!] Try later.")
        self.client.disconnect()
        break
    except Exception as e:
        print("[!] Error:", e, "\n Trying to continue...")
        continue
    else:
        if user != users[:39]:
            print(f"Waiting {delay} seconds")
            time.sleep(delay)
print('\nEnd of the program')
self уберите, вы не используете классы
 
Спасибо, за хорошую статью.
 
Может кто подсказать как подключить прокси?
 
он после каждой смены аккаунта будет спамить первые 40 юзеров?
 
Не работает((((
line 14, in <module>
if not сlient.is_user_authorized():
NameError: name 'сlient' is not defined. Did you mean: 'client'?
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab