Статья Автоматизированный сбор данных в чатах и рассылка для 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:
 
Последнее редактирование модератором:

DragonSov

Codeby Team
Red Team
03.12.2019
29
57
Привет. У тебя на самой первой картинке водяной знак от какого-то фотостока. Картинки для статей должны быть под лицензией Creative Commons (разрешены для использования без упоминания автора). В целом статья нормальная, только ты не очень правильно используешь list comprehension (генератор списка). Да и название статьи противоречит законам РФ, нужно сменить на что-то более "безобидное"
 
Последнее редактирование:
  • Нравится
Реакции: Dzen

StripedBear

Green Team
24.07.2021
24
14
Привет. У тебя на самой первой картинке водяной знак от какого-то фотостока. Картинки для статей должны быть под лицензией Creative Commons (разрешены для использования без упоминания автора). В целом статья нормальная, только ты не очень правильно используешь list comprehension (генератор списка). Да и название статьи противоречит законам РФ, нужно сменить на что-то более "безобидное"
Привет! Спасибо за поправки.
Где неправильно в list comprehension или что конкретно мне гуглить?
 

DragonSov

Codeby Team
Red Team
03.12.2019
29
57
Привет! Спасибо за поправки.
Где неправильно в 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]
 

Архонт

Green Team
03.12.2019
19
7
есть сомнения по поводу
if dialog.is_group and dialog.is_channel
разве может канал быть одновременно и группой?
 

CbIH_AKTEPA

New member
01.06.2020
1
0
Спасибо за статью!
Можешь подсказать, где ты смотришь лимиты сообщений?
 

MLNK

Mod. Ethical Hacking
Red Team
23.01.2018
548
699
коннектор клиента(как это назвать по-русски??), сбор участников чата и рассылка по пользователям.
Клиентский коннектор, но лично мне больше нравиться прямой перевод - разъем клиента.)
вообще порой лучше не переводить термины. Connector - Grabber - Sender и всем всё понятно.

в итоге ты бота тестил? сколько сообщений смог разослать до бана?
 

StripedBear

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

в итоге ты бота тестил? сколько сообщений смог разослать до бана?
Да, успешно тестил. 38-40 сообщений в день с одного аккаунта отсылается. Да, немного, но для моей задачи отлично подошло. Пять аккаунтов за пять дней - 1000 сообщений.
Если flood error - удаляю сессию и откладываю аккаунт на день.
 
  • Нравится
Реакции: MLNK

NONAME23

New member
13.06.2022
2
0
Выдает ошибку , ругается на 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
 

StripedBear

Green Team
24.07.2021
24
14
Выдает ошибку , ругается на 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
покажите весь код, пожалуйста
 

NONAME23

New member
13.06.2022
2
0
Все данные (телефон и тд были указаны.)

покажите весь код, пожалуйста
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')
 

StripedBear

Green Team
24.07.2021
24
14
Все данные (телефон и тд были указаны.)


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 уберите, вы не используете классы
 
Мы в соцсетях: