06 ноября 2019

Пишем простой граббер для Telegram чатов на Python

Пишу, перевожу и иллюстрирую IT-статьи. На proglib написал 140 материалов. Увлекаюсь Python, вебом и Data Science. Открыт к диалогу – ссылки на соцсети и мессенджеры: https://matyushkin.github.io/links/ Если понравился стиль изложения, упорядоченный список публикаций — https://github.com/matyushkin/lessons
Рассказываем, как собрать данные участников и сообщения из чатов/каналов Telegram с помощью Python и библиотеки Telethon.
77
Пишем простой граббер для Telegram чатов на Python

Работа мечты в один клик 💼

Работа в Сбере: пройди собеседование и получи оффер за 15 минут

💭Мечтаешь работать в Сбере, но не хочешь проходить десять кругов HR-собеседований? Теперь это проще, чем когда-либо!

💡AI-интервью за 15 минут – и ты уже на шаг ближе к своей новой работе.

Как получить оффер?
📌 Зарегистрируйся
📌 Пройди AI-интервью
📌 Получи обратную связь сразу же!

HR больше не тянут время – рекрутеры свяжутся с тобой в течение двух дней! 🚀

Реклама. ПАО СБЕРБАНК, ИНН 7707083893. Erid 2VtzquscAwp


В данном туториале мы научимся собирать данные и сообщения участников чатов и каналов Telegram, а также сохранять эту информацию в виде JSON-файлов, которые далее легко анализировать или экспортировать в базы данных.

Для указанных задач будет использоваться Python не ниже версии 3.5, а также высокоуровневая библиотека для работы с Telegram API – Telethon. Установить библиотеку можно с помощью менеджера пакетов pip:

        pip3 install telethon
    

Регистрируем в Telegram новое приложение

Для подключения к Telegram API необходимы api_id и api_hash. Эти параметры выдаются при регистрации приложения в инструментах разработчика (при отсутствии доступа используйте VPN). Для авторизации указываем номер телефона, к которому привязан аккаунт Telegram.

Пишем простой граббер для Telegram чатов на Python

Вводим пришедший в Telegram численно-буквенный код и попадаем на страницу регистрации нового приложения. Заполняем форму, достаточно первых двух граф:

Пишем простой граббер для Telegram чатов на Python

В результате попадаем на страницу конфигурации приложения. Находим оба параметра, а также доступные MTProto-сервера и открытые (публичные) ключи.

Избегая проблем с безопасностью, сохраняем учетные данные в отдельном файле config.ini следующей структуры:

        [Telegram]
api_id = Telegram-API-ID
api_hash = Telegram-API-Hash
username = Your-Telegram-Username
    

Поле username далее будет использоваться лишь для автоматического сохранения сессии под именем username.session. Одному клиенту соответствует одна сессия, учтите это в случае запуска нескольких клиентов.

🐍🎓 Библиотека собеса по Python
Подтянуть свои знания по Python вы можете на нашем телеграм-канале «Библиотека собеса по Python»
🐍🧩 Библиотека задач по Python
Интересные задачи по Python для практики можно найти на нашем телеграм-канале «Библиотека задач по Python»

Создаем клиент Telegram

Начнем с импорта библиотек.

        import configparser
import json

from telethon.sync import TelegramClient
from telethon import connection

# для корректного переноса времени сообщений в json
from datetime import date, datetime

# классы для работы с каналами
from telethon.tl.functions.channels import GetParticipantsRequest
from telethon.tl.types import ChannelParticipantsSearch

# класс для работы с сообщениями
from telethon.tl.functions.messages import GetHistoryRequest
    

Встроенные модули configparser и json применяем соответственно для чтения параметров и вывода данных. Из библиотеки Telethon импортируем класс клиента Telegram и класс исключений. Внутренний модуль connection необходим при использовании прокси-сервера. Остальные элементы модуля telethon.tl используются для запросов необходимых нам списков (участников канала/чата и их сообщений).

Теперь считаем учетные данные из config.ini:

        # Считываем учетные данные
config = configparser.ConfigParser()
config.read("config.ini")

# Присваиваем значения внутренним переменным
api_id   = config['Telegram']['api_id']
api_hash = config['Telegram']['api_hash']
username = config['Telegram']['username']
    

Создадим объект клиента Telegram API:

        client = TelegramClient(username, api_id, api_hash)
    

При необходимости прописываем прокси. При использовании протокола MTProxy прокси задается в виде кортежа (сервер, порт, ключ).

        proxy = (proxy_server, proxy_port, proxy_key)

client = TelegramClient(username, api_id, api_hash,
    connection=connection.ConnectionTcpMTProxyRandomizedIntermediate,
    proxy=proxy)
    

Запускаем клиент:

        client.start()
    

При первом запуске платформа запросит номер телефона, и вслед – код подтверждения. Так же, как если бы вы входили в учетную запись в приложении или браузере.

Для сбора, обработки и сохранения информации мы создадим две функции:

  1. dump_all_participants(сhannel) заберет данные о пользователях администрируемого нами сообщества channel;
  2. dump_all_messages(сhannel)соберет все сообщения. Для этой функции достаточно, чтобы у вас был доступ к сообществу (необязательно быть администратором).

Обе функции будут вызываться в теле функции main, в которой пользователь передаст ссылку на интересующий источник:

        url = input("Введите ссылку на канал или чат: ")
channel = await client.get_entity(url)
    

Касательно написания вызова функций стоит оговориться, что Telethon является асинхронной библиотекой. Поэтому в коде используются операторы async и await. В связи с этим функция main полностью будет выглядеть так:

        async def main():
	url = input("Введите ссылку на канал или чат: ")
	channel = await client.get_entity(url)
	await dump_all_participants(channel)
	await dump_all_messages(channel)
    

Заметим, что из-за асинхронности Telethon может некорректно работать в средах, использующих те же подходы (Anaconda, Spyder, Jupyter).

Рекомендуемым способом управления клиентом является менеджер контекстов with. Его мы запустим в конце скрипта после описания вложенных в main функций.

        with client:
	client.loop.run_until_complete(main())
    

Собираем данные об участниках

Telegram не выводит все запрашиваемые данные за один раз, а выдает их в пакетном режиме, по 100 записей за каждый запрос.

        async def dump_all_participants(channel):
	"""Записывает json-файл с информацией о всех участниках канала/чата"""
	offset_user = 0    # номер участника, с которого начинается считывание
	limit_user = 100   # максимальное число записей, передаваемых за один раз

	all_participants = []   # список всех участников канала
	filter_user = ChannelParticipantsSearch('')

	while True:
		participants = await client(GetParticipantsRequest(channel,
			filter_user, offset_user, limit_user, hash=0))
		if not participants.users:
			break
		all_participants.extend(participants.users)
		offset_user += len(participants.users)
    

Устанавливаем ограничение в 100, начинаем со смещения 0, создаем список всех участников канала all_participants. Внутри бесконечного цикла передаем запрос GetParticipantsRequest.

Проверяем, есть ли у объекта participants свойство users. Если нет, выходим из цикла. В обратном случае добавляем новых членов в список all_participants, а длину полученного списка добавляем к смещению offset_user. Следующий запрос забирает пользователей, начиная с этого смещения. Цикл продолжается до тех пор, пока не соберет всех фолловеров канала.

Самый простой способ сохранить собранные данные в структурированном виде – воспользоваться форматом JSON. Базы данных, такие как MySQL, MongoDB и т. д., стоит рассматривать лишь для очень популярных каналов и большого количества сохраняемой информации. Либо если вы планируете такое расширение в будущем.

В JSON-файле можно хранить и всю информацию о каждом пользователе, но обычно достаточно лишь нескольких параметров. Покажем на примере, как ограничиться набором определенных данных:

        	all_users_details = []   # список словарей с интересующими параметрами участников канала

	for participant in all_participants:
		all_users_details.append({"id": participant.id,
			"first_name": participant.first_name,
			"last_name": participant.last_name,
			"user": participant.username,
			"phone": participant.phone,
			"is_bot": participant.bot})

	with open('channel_users.json', 'w', encoding='utf8') as outfile:
		json.dump(all_users_details, outfile, ensure_ascii=False)
    

Итак, для каждого пользователя создается свой словарь данных и добавляется в общий список all_user_details, который записывается в JSON-файл.

🐍 Библиотека питониста
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста»

Собираем сообщения

Ситуация со сбором сообщений идентична сбору сведений о пользователях. Отличия сводятся к трем пунктам:

  1. Вместо клиентского запроса GetParticipantsRequest необходимо отправить GetHistoryRequest со своим набором параметров. Так же, как и в случае со списком участников запрос ограничен сотней записей за один раз.
  2. Для списка сообщений важна их последовательность. Чтобы получать последние сообщения, нужно правильно задать смещение в GetHistoryRequest (с конца).
  3. Чтобы корректно сохранить данные о времени публикации сообщений в JSON-файле, нужно преобразовать формат времени.

Итоговый код:

        import configparser
import json

from telethon.sync import TelegramClient
from telethon import connection

# для корректного переноса времени сообщений в json
from datetime import date, datetime

# классы для работы с каналами
from telethon.tl.functions.channels import GetParticipantsRequest
from telethon.tl.types import ChannelParticipantsSearch

# класс для работы с сообщениями
from telethon.tl.functions.messages import GetHistoryRequest

# Считываем учетные данные
config = configparser.ConfigParser()
config.read("config.ini")

# Присваиваем значения внутренним переменным
api_id   = config['Telegram']['api_id']
api_hash = config['Telegram']['api_hash']
username = config['Telegram']['username']

proxy = (proxy_server, proxy_port, proxy_key)

client = TelegramClient(username, api_id, api_hash,
    connection=connection.ConnectionTcpMTProxyRandomizedIntermediate,
    proxy=proxy)

client.start()


async def dump_all_participants(channel):
	"""Записывает json-файл с информацией о всех участниках канала/чата"""
	offset_user = 0    # номер участника, с которого начинается считывание
	limit_user = 100   # максимальное число записей, передаваемых за один раз

	all_participants = []   # список всех участников канала
	filter_user = ChannelParticipantsSearch('')

	while True:
		participants = await client(GetParticipantsRequest(channel,
			filter_user, offset_user, limit_user, hash=0))
		if not participants.users:
			break
		all_participants.extend(participants.users)
		offset_user += len(participants.users)

	all_users_details = []   # список словарей с интересующими параметрами участников канала

	for participant in all_participants:
		all_users_details.append({"id": participant.id,
			"first_name": participant.first_name,
			"last_name": participant.last_name,
			"user": participant.username,
			"phone": participant.phone,
			"is_bot": participant.bot})

	with open('channel_users.json', 'w', encoding='utf8') as outfile:
		json.dump(all_users_details, outfile, ensure_ascii=False)


async def dump_all_messages(channel):
	"""Записывает json-файл с информацией о всех сообщениях канала/чата"""
	offset_msg = 0    # номер записи, с которой начинается считывание
	limit_msg = 100   # максимальное число записей, передаваемых за один раз

	all_messages = []   # список всех сообщений
	total_messages = 0
	total_count_limit = 0  # поменяйте это значение, если вам нужны не все сообщения

	class DateTimeEncoder(json.JSONEncoder):
		'''Класс для сериализации записи дат в JSON'''
		def default(self, o):
			if isinstance(o, datetime):
				return o.isoformat()
			if isinstance(o, bytes):
				return list(o)
			return json.JSONEncoder.default(self, o)

	while True:
		history = await client(GetHistoryRequest(
			peer=channel,
			offset_id=offset_msg,
			offset_date=None, add_offset=0,
			limit=limit_msg, max_id=0, min_id=0,
			hash=0))
		if not history.messages:
			break
		messages = history.messages
		for message in messages:
			all_messages.append(message.to_dict())
		offset_msg = messages[len(messages) - 1].id
		total_messages = len(all_messages)
		if total_count_limit != 0 and total_messages >= total_count_limit:
			break

	with open('channel_messages.json', 'w', encoding='utf8') as outfile:
		 json.dump(all_messages, outfile, ensure_ascii=False, cls=DateTimeEncoder)


async def main():
	url = input("Введите ссылку на канал или чат: ")
	channel = await client.get_entity(url)
	await dump_all_participants(channel)
	await dump_all_messages(channel)


with client:
	client.loop.run_until_complete(main())
    

Если для анализа сообщений потребуются не все записи, задайте их число в переменной total_count_limit. Если нужна только сборка сообщений канала, достаточно закомментировать вызов await dump_all_participants(channel).

Таким образом, с помощью Python и Telethon мы написали скрипт, собирающий и сохраняющий данные и реплики участников сообществ Telegram.

Есть ли у вас опыт работы с Telegram API?

Комментарии

 
13 июля 2024

здраствуйте кто может мне создать это по инструкцию ? свяжитесь со мной

Почему-то после использования telethone выходит из аккаунта на всех устройствах. Что с этим можно сделать?

06 сентября 2023

Та же картина Авторизация через telethone - через минуту выход на всех устройствах

13 октября 2023

в client = TelegramClient добавил system_version="4.16.30-vxCUSTOM" помогло

23 октября 2024

Час добрый, вы нашли решение по этому вопросу? Я столкнулся с ситуацией-авторизацией пользователей в боте по номеру телефона. После ввода пароля выходит из аккаунта на всех устройствах. Если есть инфа, подскажите пожалуйста.

Стоит облачный пароль на аккаунте, при авторизации символы в строке ввода для пароля просто не вводятся! Как быть?

10 апреля 2023

Как достать поле Bio (описание) в participant ?? если это возможно, или только first_name и т п?

28 марта 2023

Здравствуйте! Собирает информацию лишь о 200 участниках, когда их 1500. В чем проблема?

Не всего лишь 200 а в одном блоке он тащит инфо о 200 участниках и так каждый раз без нарушения лимита .

23 января 2023

Добрый день! Почему-то получает меньше пользователей, чем по факту есть канале, как понять почему, и как это исправить?

05 января 2023

А можно ли как то сделать чтобы скрипт отсеевал участников по времени их захода в TG? Ну чтобы мёртвые аккаунты и ботов он просто пропускал

12 января 2023

Статус в Telegram API можно смотреть только текущий у контактов: https://core.telegram.org/method/contacts.getStatuses

Ботов можно отличить просто по имени, если речь о телеграм-ботах. Факт удаления аккаунта указываются в свойствах юзера.

08 декабря 2022

Доброго времени суток подскажите пожалуйста какую строку изменить чтобы парсить только ФОТО

from telethon import TelegramClient, events, errors, types import asyncio import re import json

=================================================================

api_id = 1*4 api_hash = "9***6"

=================================================================

KEYS = { r"https://\S+": "https://wa.me/message/F1", * }

=================================================================

Bad_Keys = ["$","TL"]

=================================================================

tags = ''

добавление текста к посту, если не надо оставить ковычки пустыми ""

----

with TelegramClient('myApp13', api_id, api_hash) as client: print("~Activated~")

(events.NewMessage())
async def Messages(event):
    with open('channels.json', 'r+') as f:
        channels = json.load(f)
    f.close()
    ev_channel = await client.get_entity(types.PeerChannel(event.message.peer_id.channel_id))
    for ch in channels:
        if ch == f'@{ev_channel.username}':
            if not [element for element in Bad_Keys if event.raw_text.lower().__contains__(element)]:

                text = event.raw_text

                with open('Hashtags.json', 'r+') as f:
                    Hashtags = json.load(f)
                f.close()

                for i in Hashtags:
                    if i == f'@{ev_channel.username}':
                        text = ''
                        text += f'{Hashtags[i]}\n{event.raw_text}'

                for i in KEYS:
                    text = re.sub(i, KEYS[i], text)

                if not event.grouped_id and not event.message.forward:
                    try:
                        await client.send_message(
                            entity=channels[ch],
                            file=event.message.media,
                            message=text + tags,
                            parse_mode='md',
                            link_preview=False)
                    except errors.FloodWaitError as e:
                        print(f'[!] Ошибка флуда ждем: {e.seconds} секунд')
                        await asyncio.sleep(e.seconds)
                    except Exception as e:
                        print('[!] Ошибка', e)
                elif event.message.text and not event.message.media and not event.message.forward and not event.grouped_id:
                    try:
                        await client.send_message(channels[ch], text+tags, parse_mode='md', link_preview=False)
                    except errors.FloodWaitError as e:
                        print(f'[!] Ошибка флуда ждем: {e.seconds} секунд')
                        await asyncio.sleep(e.seconds)
                    except Exception as e:
                        print('[!] Ошибка', e)
                elif event.message.forward:
                    try:
                        await client.send_message(channels[ch], text+tags, parse_mode='md', link_preview=False)
                    except errors.FloodWaitError as e:
                        print(f'[!] Ошибка флуда ждем: {e.seconds} секунд')
                    except Exception as e:
                        print('[!] Ошибка', e)

(events.Album())
async def Album(event):
    my_channel_a = await client.get_entity(types.PeerChannel(event.original_update.message.peer_id.channel_id))
    with open('channels.json', 'r+') as f:
        channels = json.load(f)
    f.close()
    for ch in channels:
        if ch == f'@{my_channel_a.username}':
            text = event.original_update.message.message
            if not [element for element in Bad_Keys if text.lower().__contains__(element)]:
                for i in KEYS:
                    text = re.sub(i, KEYS[i], text)

                text = event.raw_text

                with open('Hashtags.json', 'r+') as f:
                    Hashtags = json.load(f)
                f.close()

                for i in Hashtags:
                    if i == f'@{my_channel_a.username}':
                        text = ''
                        text += f'{Hashtags[i]}\n{event.raw_text}'

                for i in KEYS:
                    text = re.sub(i, KEYS[i], text)

                try:
                    await client.send_message(
                        entity=channels[ch],
                        file=event.messages,
                        message=text + tags,
                        parse_mode='md',
                        link_preview=False)
                except errors.FloodWaitError as e:
                    print(f'[!] Ошибка флуда ждем: {e.seconds} секунд')
                    await asyncio.sleep(e.seconds)
                except Exception as e:
                    print('[!] Ошибка', e)
client.run_until_disconnected()
17 октября 2022

Спасибо за подробную статью, очень полезно, особенно для начинающих вроде меня. Если не сложно, не могли бы вы подсказать, как сделать небольшую доработку, а именно при скачивании сообщениий скачивать только новые. Я сделал на основе вашего кода сохранялку картинок из канала, но никак не могу разобраться с определением непрочитанности, чтобы не скачивать повторно. Я так понял, у собственно message нет свойства unread, значит надо как-то определять последнее прочитанное сообщение через get_dialogs и дальше уже отталкиваться от него. (Хотя получается, в списке сообщений не может быть непрочитанных в середине? как-то странно, прыгнул на последнее, прочитал его, а прочитанными отмечены теперь все?) Но как именно совместить channel и get_dialogs я так и не понял. Вопрос этот возникает постоянно, автор отправляет RTFM, но ни там, ни где-то еще внятного ответа я так и не нашел.

09 октября 2022

что делать если ошибка name 'proxy_server' is not defined

12 октября 2022

Это значит, что где-то используется имя proxy_server, но само значение не было задано. Если вы не используете прокси-сервер, его упоминать не нужно.

17 октября 2022

То же самое. Что делать? proxy = (proxy_server, proxy_port, proxy_key). Так что с ним делать? И где эти данные брать?

18 октября 2022

убрать эту строку и параметр proxy=proxy из инициализации клиента client = TelegramClient(username, api_id, api_hash)

17 сентября 2022

Как сделать чтоб можна вводить несколько тг каналов подряд? спасибо

12 октября 2022

Переберите их в цикле или задайте списком.

03 сентября 2022

как сделать запрос к стене не через библиотеку а прямым методом api?

12 октября 2022

Даже если не использовать обертку для API, всё равно разумно использовать библиотеку для запросов — requests. О том, как работать с API в Python есть отдельная статья: https://proglib.io/p/python-i-api-prevoshodnoe-kombo-dlya-avtomatizacii-raboty-s-publichnymi-dannymi-2021-02-26

Все методы Telegram API перечислены здесь: https://proglib.io/p/python-i-api-prevoshodnoe-kombo-dlya-avtomatizacii-raboty-s-publichnymi-dannymi-2021-02-26

13 августа 2022

Здраствуйте а можно сделать так чтобы не ограничивался 10000 а всех участников чата спарсил

Добрый день, подскажите пжлст в чем может причина? выдает следующую ошибку при запуске клиента: <coroutine object AuthMethods._start at 0x06B7F978> Работаю в Jupyter (Anaconda)

Но разве это ошибка? Это всего лишь сообщение-предупреждение от API. После сообщения перестает выполняться остальной код?

Добрый день, подскажите где взять эти данные ? При необходимости прописываем прокси. При использовании протокола MTProxy прокси задается в виде кортежа (сервер, порт, ключ). У вас есть телеграм? чтобы спросить детальнее по коду?

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

28 июня 2022

Добрый день, есть ли предположения, почему парсит только 200 пользователей из общего числа?

Красота все как по маслу) после небольшого редактирования) Автору благодарочка)

02 июня 2022

Всем привет. При запуске после ввода url появляется ошибка. Подскажите как лечить

Traceback (most recent call last): File "c:\Users\Артём\Documents\less\graber.py", line 108, in client.loop.run_until_complete(main()) File "C:\Users\Артём\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 646, in run_until_complete return future.result() File "c:\Users\Артём\Documents\less\graber.py", line 102, in main channel = await client.get_entity(url) File "C:\Users\Артём\AppData\Local\Programs\Python\Python310\lib\site-packages\telethon\client\users.py", line 335, in get_entity
result.append(await self._get_entity_from_string(x)) File "C:\Users\Артём\AppData\Local\Programs\Python\Python310\lib\site-packages\telethon\client\users.py", line 574, in _get_entity_from_string raise ValueError(

Ты вставляешь ссылку канала,а скрипт парсит только группы

Здравствуйте! подскажите пожалуйста. после запуска скрипта открывается окно на мгновение и более ничего не происходит в чем может быть проблема?

Запустите программу из терминала (командной строки) или интерпретатора Python – так будет выведено описание ошибки/проблемы.

Спасибо Вам за подсказку)) заработало!

25 апреля 2022

async def main(): url = input("https://t.me/bjornborg_tennis") channel = await client.get_entity(url) await dump_all_participants(channel) await dump_all_messages(channel)

File "/home/zxxrc/.local/lib/python3.10/site-packages/telethon/client/users.py", line 574, in _get_entity_from_string raise ValueError( ValueError: Cannot find any entity corresponding to ""

Вот тут выдает ошибку, может кто знает как исправить ?

25 апреля 2022

В функции input() не нужно было менять строку "Введите ссылку на канал или чат: " — это то, что программа выводит на экран в качестве приглашения для пользователя. А саму url вводит пользователь программы.

В результате вы ввели пустую строку, о чем и сообщает ошибка (Cannot find any entity corresponding to ""). Код не смог найти канал с пустым url.

Если вы работаете только с одним каналом, можете просто задать неменяемое строковое значение url="https://t.me/bjornborg_tennis".

11 апреля 2022

Здравствуйте! Такой вопрос по поводу парсинга ТГ. Можно ли парсить закрытые группы, чаты в ТГ, не являясь администратором, но состоя в группе в качестве участника? Если да, то какие методы использовать? ЯП - Python. Спасибо!

Спасибо! А если мне нужно парсить не сообщения, а данные об участниках закрытой группы?

Если вы состоите в закрытом чате телеграм, вам доступен список участников. Аналогично должно работать для бота.

22 января 2022

Большое спасибо. Получил текст сообщений, а это ж самое главное) Не думаете переписать код на чем -нибудь компилируемом, например, на Go?

22 января 2022

Да, были такие предложения (как и оформить в виде микросервиса). Пока не хватает времени. Если кто-то поможет, будет замечательно.

09 сентября 2021

Создал файл .ini с нужными параметрами и кодировкой, при старте клиента спросил номер телефона, ввёл в формате: +79156465654. Затем последовала ошибка:

Traceback (most recent call last): File "<pyshell#18>", line 1, in client.start() File "C:...\telethon\client\auth.py", line 133, in start else self.loop.run_until_complete(coro) File "C:...\lib\asyncio\base_events.py", line 642, in run_until_complete return future.result() File "C:...\lib\site-packages\telethon\client\auth.py", line 189, in _start await self.send_code_request(phone, force_sms=force_sms) File "C:...\telethon\client\auth.py", line 514, in send_code_request result = await self(functions.auth.SendCodeRequest( File "C:...\telethon\client\users.py", line 30, in call return await self._call(self._sender, request, ordered=ordered) File "C:...\telethon\client\users.py", line 79, in _call result = await future telethon.errors.rpcerrorlist.ApiIdInvalidError: The api_id/api_hash combination is invalid (caused by SendCodeRequest)

04 июня 2021

Автору спасибо! Кто уже разобрался с тем что тут написано: Ребята помогите собрать сообщения так чтоб в итоге получилась табличка в ексельке Имя, идентификатор в телеге, сообщение. Закину за работу копеечку, а заодно вы потренируетесь :))) alexey(точка)betim(собака)gmail(точка)com

05 января 2023

в excel выбери параметр через запятые

26 декабря 2020

Я новичок в Питоне, до этого кодил на Си-Шарпе. Подскажите, где взять proxy_server, proxy_port, proxy_key?

26 декабря 2020

Это не часть языка, а настройки прокси-соединения. Если вы не используете прокси (например, на территории РФ телеграм более не блокируется), то эти настройки можно пропустить.

26 декабря 2020

я понял, что настройки прокси. Я имею в виду, что в my.telegram.org выданы только адрес и порт, а ключ где взять?

26 декабря 2020

В статье указано, что использовался MTProxy, у него соответственно есть не только адрес, порт, но и ключ (secret):

tg://proxy?server=<АДРЕС>&port=<ПОРТ>&secret=<КЛЮЧ>

Но можно использовать и обычные HTTP-прокси (документация).

Ку админы)) есть ли исходники(сорцы) в гитхабе по этой теме?). а то всю кучу - ошибки бывают

04 ноября 2020

У Telegram регулярно обновляется API, соответственно меняется и библиотека Telethon. Статья написана год назад, в любом случае нужно сверяться с документацией.

22 сентября 2020

Как реализовать функцию автоматического нажатия определенной кнопки с заданным интервалом времени в меню чужого бота?

22 сентября 2020

Нажатие фактически является сообщением. В документации телеграм сказано следующее (перевожу):

«Боты, разговаривающие друг с другом, потенциально могут застрять в нежелательных циклах. Чтобы этого избежать, мы решили, что боты не смогут видеть сообщения от других ботов независимо от режима их использования».

09 сентября 2020

А как можно реализовать, через библиотеку JSON, чтобы в терминал выводилось последнее сообщение,(опционально) минуя запись в сам файл JSON? И кстати сам питон ругается на async def, говоря что это синтаксическая ошибка, кто то смог решить эту проблему? Система Raspbian

06 августа 2020

А как можно действовать если доступ к каналу есть, как у пользователя, а ссылки на канал нет?

06 августа 2020

Посмотреть в информации о канале.

22 июня 2020

result = await future telethon.errors.rpcerrorlist.ChatAdminRequiredError: Chat admin privileges are required to do that in the specified chat (for example, to send a message in a channel which is not yours), or invalid permissions used for the channel or group (caused by GetParticipantsRequest)

я так понимаю этот метод подходит только для каналов и чатов где есть права администратора?

Конечно. У библиотеки те же права доступа к сведениям об участниках, что и у пользователя.

18 июня 2020

"При первом запуске платформа запросит номер телефона, и вслед – код подтверждения. Так же, как если бы вы входили в учетную запись в приложении или браузере."

До этого вставил весь код, создал конфиг, ввел туда апи ид и хеш и юзернейм с @ ничего не происходит при запуске

У Telethon и Telegram довольно часто обновляются API. Статья написана более полугода назад. Проверьте, не изменился ли способ подключения.

27 августа 2021

Добрый день!

А с часовыми поясами проблем не было? Не отображает текущий часовой пояс, выдает -3 часа от сообщений в чате.

24 апреля 2020

Всем привет. Только учу язык, решил попрактиковаться. Где файл JSON найти?

 
24 апреля 2020

Он создаётся в процессе работы программы.

19 ноября 2021

По умолчанию файл создаётся в том же каталоге, где запущен скрипт.

10 апреля 2020

Получил результат - блокировка аккаунта как только залогинил в проге акк) спасибо

10 апреля 2020

Странно. Тут нет ничего вредоносного, используется стандартная библиотека подключения к API. Скорее всего, это как-то свяазно с обновлением telethon, прошло уже полгода с выхода статьи.

01 января 2020

Привет. У меня не заработало пока не сохранил config.ini в кодировке UTF-8 без BOM, и не переписал считывание учетных данных через

Считываем учетные данные

config = configparser.ConfigParser() path = '/'.join((os.path.abspath(file).replace('\', '/')).split('/')[:-1]) config.read(os.path.join(path, 'config.ini'))

П.С. и там в самом начале, где считывание учетных данных в статье, наверное опечатка:

Считываем учетные данные

config = configparser.ConfigParser() config.read("config2.ini")

Вместо config2.ini должно быть просто config.ini

01 января 2020

Спасибо, опечатку поправлю, просто использовал два конфигурационных файла. С первой проблемой из-под Linux не сталкивался.

05 февраля 2020

А можно делать парсинг сообщений не по URL канала, а по его id? И как это сделать?

Привет, а как сохранить в этой кодировке?

07 июля 2021

Запутите в своей системе скрипт, который сам создаст файл в нужной кодировке:

import configparser
cfg = configparser.ConfigParser()
cfg.add_section("Telegram")
cfg.set("Telegram", "api_id", "Place your 'api_id' here.")
cfg.set("Telegram", "api_hash", "Place your 'api_hash' here.")
cfg.set("Telegram", "username", "Place your 'username' here.")
with open('config.ini', 'w') as my_cfg:
    cfg.write(my_cfg)

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

LIVE >

Подпишись

на push-уведомления