{
    "version": "https:\/\/jsonfeed.org\/version\/1",
    "title": "Блог об аналитике, визуализации данных, data science и BI, заметки с тегом: telethon",
    "home_page_url": "http:\/\/test.leftjoin.ru\/tags\/telethon\/",
    "feed_url": "http:\/\/test.leftjoin.ru\/tags\/telethon\/json\/",
    "icon": "http:\/\/test.leftjoin.ru\/user\/userpic@2x.jpg",
    "author": {
        "name": "Николай Валиотти",
        "url": "http:\/\/test.leftjoin.ru\/",
        "avatar": "http:\/\/test.leftjoin.ru\/user\/userpic@2x.jpg"
    },
    "items": [
        {
            "id": "95",
            "url": "http:\/\/test.leftjoin.ru\/all\/tg-api-parse\/",
            "title": "Сбор информации о подписчиках Telegram-канала",
            "content_html": "<p>На 2021 год боты в Telegram так и не имеют метода, позволяющего получать информацию о подписчиках канала. Тем не менее, существует достаточно сложное в освоении Telegram API и построенная на нём библиотека Telethon. Сегодня мы посмотрим, как при помощи библиотеки выгрузить информацию о подписчиках своего канала.<\/p>\n<h2>Создание приложения<\/h2>\n<p>Для начала необходимо создать приложение, через которое будут отправляться запросы к API. Перейдите на <a href=\"https:\/\/my.telegram.org\">https:\/\/my.telegram.org<\/a> и авторизуйтесь в Telegram-аккаунте:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"http:\/\/test.leftjoin.ru\/pictures\/1-24.png\" width=\"532\" height=\"299\" alt=\"\" \/>\n<\/div>\n<p>После успешной авторизации перейдите на страницу API development tools:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"http:\/\/test.leftjoin.ru\/pictures\/2-22.png\" width=\"397\" height=\"190\" alt=\"\" \/>\n<\/div>\n<p>Заполните все поля и жмите на создание приложения:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"http:\/\/test.leftjoin.ru\/pictures\/3-20.png\" width=\"645\" height=\"478\" alt=\"\" \/>\n<\/div>\n<p>Из полученной конфигурации нам необходим app api_id и app api_hash:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"http:\/\/test.leftjoin.ru\/pictures\/5-13.png\" width=\"629\" height=\"123\" alt=\"\" \/>\n<\/div>\n<h2>Запрос к API<\/h2>\n<p>Импортируем telethon — он поможет сформировать запрос, и pandas — полученный ответ мы запишем в DataFrame.<\/p>\n<pre class=\"e2-text-code\"><code>from telethon import TelegramClient\r\nimport pandas as pd<\/code><\/pre><p>Вводим api_id, api_hash, наш номер телефона и ссылку на канал, информацию о подписчиках которого хотим получить. Доступ к информации о подписчиках есть только у администраторов канала.<\/p>\n<pre class=\"e2-text-code\"><code>api_id = 1234567\r\napi_hash = '1b42hj25kd8jw42b234kwj242c'\r\nphone = '+71234567890'\r\nchannel_href = 'https:\/\/t.me\/leftjoin'<\/code><\/pre><p>Создаём новую сессию — вместо session_name можно подставить любое другое название. Методы в библиотеке работают асинхронно, поэтому ответа от них требуется ожидать:<\/p>\n<pre class=\"e2-text-code\"><code>client = TelegramClient('session_name', api_id, api_hash)\r\nclient = await client.start()\r\ndialogs = await client.get_dialogs()<\/code><\/pre><p>Собираем все каналы текущего пользователя. Из ссылки забираем часть с именем канала и вытаскиваем из словаря нужный:<\/p>\n<pre class=\"e2-text-code\"><code>channels = {d.entity.username: d.entity\r\n            for d in dialogs\r\n            if d.is_channel}\r\nmy_channel = channel_href.split('\/')[-1]\r\nchannel = channels[my_channel]<\/code><\/pre><p>Подписчиков, доступ к которым не ограничен приватностью, можно получить методом get_participants. С 20 июля 2018 года Telegram установил ограничение в 200 подписчиков для вызова метода, и установка параметра aggressive на True поможет получить всех подписчиков за раз.<\/p>\n<pre class=\"e2-text-code\"><code>members_telethon_list = await client.get_participants(channel, aggressive=True)<\/code><\/pre><p>Из полученных библиотечных структур извлекаем информацию о пользователях — их имена и телефоны:<\/p>\n<pre class=\"e2-text-code\"><code>username_list = [member.username for member in members_telethon_list]\r\nfirst_name_list = [member.first_name for member in members_telethon_list]\r\nlast_name_list = [member.last_name for member in members_telethon_list]\r\nphone_list = [member.phone for member in members_telethon_list]<\/code><\/pre><p>Из четырёх списков собираем DataFrame и пишем его в csv-таблицу:<\/p>\n<pre class=\"e2-text-code\"><code>df = pd.DataFrame()\r\ndf['username'] = username_list\r\ndf['first_name'] = first_name_list\r\ndf['last_name'] = last_name_list\r\ndf['phone'] = phone_list\r\ndf.to_csv('subscribers.csv', index=False)<\/code><\/pre><p>Результат работы — такая таблица:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"http:\/\/test.leftjoin.ru\/pictures\/6-13.png\" width=\"327\" height=\"191\" alt=\"\" \/>\n<\/div>\n<p>Для запуска в Jupyter Notebook описанный ниже код можно просто вставить в ячейку, но при запуске из Python-файла будет такая ошибка:<\/p>\n<pre class=\"e2-text-code\"><code>SyntaxError: 'await' outside function<\/code><\/pre><p>Устранить проблему можно, записав весь код в асинхронную функцию. Целиком выглядеть код будет так:<\/p>\n<pre class=\"e2-text-code\"><code>from telethon import TelegramClient\r\nimport pandas as pd\r\nimport asyncio\r\n\r\nasync def main():\r\n        api_id = 1234567\r\n        api_hash = '1b42hj25kd8jw42b234kwj242c'\r\n        phone = '+71234567890'\r\n        channel_href = 'https:\/\/t.me\/leftjoin'\r\n\r\n\tclient = TelegramClient('session_name', api_id, api_hash)\r\n\tclient = await client.start()\r\n\tdialogs = await client.get_dialogs()\r\n\r\n\tchannels = {d.entity.username: d.entity\r\n\t\t\t\tfor d in dialogs\r\n\t\t\t\tif d.is_channel}\r\n\tmy_channel = channel_href.split('\/')[-1]\r\n\tchannel = channels[my_channel]\r\n\r\n\tmembers_telethon_list = await client.get_participants(channel, aggressive=True)\r\n\r\n\tusername_list = [member.username for member in members_telethon_list]\r\n\tfirst_name_list = [member.first_name for member in members_telethon_list]\r\n\tlast_name_list = [member.last_name for member in members_telethon_list]\r\n\tphone_list = [member.phone for member in members_telethon_list]\r\n\r\n\tdf = pd.DataFrame()\r\n\tdf['username'] = username_list\r\n\tdf['first_name'] = first_name_list\r\n\tdf['last_name'] = last_name_list\r\n\tdf['phone'] = phone_list\r\n\tdf.to_csv('subscribers.csv', index=False)\r\n\r\nif __name__ == '__main__':\r\n\tloop = asyncio.get_event_loop()\r\n\tloop.run_until_complete(main())<\/code><\/pre>",
            "date_published": "2021-02-08T15:19:17+03:00",
            "date_modified": "2021-08-30T13:46:59+03:00",
            "image": "http:\/\/test.leftjoin.ru\/pictures\/1-24.png",
            "_date_published_rfc2822": "Mon, 08 Feb 2021 15:19:17 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "95",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css"
                ],
                "og_images": [
                    "http:\/\/test.leftjoin.ru\/pictures\/1-24.png",
                    "http:\/\/test.leftjoin.ru\/pictures\/2-22.png",
                    "http:\/\/test.leftjoin.ru\/pictures\/3-20.png",
                    "http:\/\/test.leftjoin.ru\/pictures\/5-13.png",
                    "http:\/\/test.leftjoin.ru\/pictures\/6-13.png"
                ]
            }
        }
    ],
    "_e2_version": 3365,
    "_e2_ua_string": "E2 (v3365; Aegea)"
}