IT-инфраструктура для бизнеса и творчества
Разработка
Dan Kamilov

Telegram-бот для получения адреса по локации или координатам (Python)

Привет! Представь ситуацию, когда тебе скинули координаты или локацию, но ты хочешь срочно узнать адрес этого места.

Сегодня попробуем написать Telegram-бота для получения адреса по координатам или локации.

В итоге у тебя получится вот такой бот @SayMyAddressBot.

Что нам для этого потребуется?

  • Бот в Telegram;
  • Обратный геокодинг от Яндекса. Геокодинг это такой сервис, который позволяет получить из адреса координаты, а нам нужно наоборот, поэтому «обратный геокодинг»;
  • Установленный Python и библиотека requests для посылки запросов;
  • Установленная библиотека Python-telegram-bot.

Но давай обо всём по порядку!

Создаём бота в Telegram.

1) Ищем в поиске Telegram бота по нику @botfather. Этот бот ответственен за регистрацию всех остальных ботов;

@botfather

2) Отправляем ему /newbot и начинаем создание бота;

3) Отправляем имя бота (оно может быть любым) и ник бота (обязательно должен оканчиваться на «bot»). Если у тебя выходит ошибка, то значит этот ник занят. Пробуй другой.

4) Получаем токен бота (скопируй этот токен и никому не давай😅).

Скриншот ниже (токен выделен красной рамкой).

Супер! Бот создан и уже доступен внутри Telegram по нику. Можешь вбить в поиске и убедиться. Также ты можешь найти его по ссылке t.me/НикТвоегоБота. Например на скриншоте я зарегистрировал SayMyAddressBot, значит его ссылка t.me/SayMyAddressBot. Сохрани такую ссылку с ником твоего бота. Скоро она нам пригодится.

Отлично. С ботом разобрались.

Обратный геокодинг от Яндекса.

Я надеюсь, что у тебя есть аккаунт на Яндексе. Если нет, то тебе сюда.

Итак. Как работает обратный геокодинг от Яндекса?

Всё очень просто. Нужно отправить GET запрос с координатами и получить в ответ адрес.

Вот пример такого запроса:

https://geocode-maps.yandex.ru/1.x? format=json&lang=ru_RU&kind=house&geocode=37.617585,55.751903&apikey=ТОКЕН

Что мы тут видим?

Запрос:

https://geocode-maps.yandex.ru/1.x/

Параметры:

  • format: в каком формате возвращать данные. В данном случае json;
  • lang: язык возвращаемых данных. В данном случае ru_RU (русский);
  • kind: вид адреса. В данном случае house (точность до дома);
  • geocode: координаты (сначала идет долгота, затем широта);
  • apikey: токен для доступа.

P.S.: параметров гораздо больше, но нам они не нужны. Подробнее можешь почитать тут.

Просто, правда? Послал запрос с координатами, получил адрес 😊.

Как видишь у нас есть все данные кроме токена. Займемся его получением!

Получаем токен.

1) Заходим на страницу разработчика и входим в кабинет (аккаунт на Яндексе у тебя уже есть).

2) Получилось? Отлично. Далее ты увидишь вот такую страницу.

Пустой кабинет разработчика

Жми желтую кнопку «Подключить API»

3) Теперь нужно выбрать какой именно токен нам нужен.

Нам нужен HTTP геокодер

Выбирай «JavaScript API и HTTP геокодер». За ним мы и пришли.

4) Далее заполняем формочку твоими данными.

В поле «Ссылка на ваш сайт» пиши ссылку на своего бота, которую мы сохранили ранее.

Ну и тыкай кнопку «Продолжить».

5) Тебе должно всплыть окошко с сообщением об успешной регистрации.

Жми «Перейти к API».

6) Вот и всё. На открывшейся странице уже лежит наш искомый токен геокодера (выделил красной рамкой). Его тоже сохрани и никому не давай.

Токен активируется через 15 минут после создания. Можешь прямо в браузере (Chrome, Safari или что там у тебя) вбить (не забудь подставить свой токен в конце).

https://geocode-maps.yandex.ru/1.x? format=json&lang=ru_RU&kind=house&geocode=37.617585,55.751903&apikey=ТОКЕН

и получить ответ в json виде:

{ "response": { "GeoObjectCollection": { "metaDataProperty": { "GeocoderResponseMetaData": { "Point": { "pos": "37.617585 55.751903" }, "boundedBy": { "Envelope": { "lowerCorner": "37.615084 55.749405", "upperCorner": "37.620079 55.7544" } }, "request": "37.617585,55.751903", "results": "10", "found": "2" } }, "featureMember": [ { "GeoObject": { "metaDataProperty": { "GeocoderMetaData": { "precision": "exact", "text": "Russia, Moscow, Moscow Kremlin, 1", "kind": "house", "Address": { "country_code": "RU", "formatted": "Russia, Moscow, Moscow Kremlin, 1", "Components": [ { "kind": "country", "name": "Russia" }, { "kind": "province", "name": "Tsentralny federalny okrug" }, { "kind": "province", "name": "Moscow" }, { "kind": "locality", "name": "Moscow" }, { "kind": "district", "name": "Moscow Kremlin" }, { "kind": "house", "name": "1" } ] }, "AddressDetails": { "Country": { "AddressLine": "Russia, Moscow, Moscow Kremlin, 1", "CountryNameCode": "RU", "CountryName": "Russia", ...

Пол дела сделано. У нас есть и Telegram бот (с его токеном) и геокодер (с его токеном).

Теперь с помощью Python мы их объединим!

Python у тебя уже установлен? Если нет, то тебе сюда.

Получаем адрес по координатам на Python.

В Python есть библиотека requests и она позволяет посылать запросы (как ты только что делал в браузере). Это нам подходит.

1) Открывай консоль (терминал) и устанавливай requests с помощью команды:

pip install requests

Подробнее тут.

2) Теперь нужно будет написать небольшой код на Python для получения адреса по координатам.

Открывай свою среду разработки или просто текстовый файл (нужно будет сохранить его с окончанием. py, а не. txt). Назовём файл main.py.

И добавляй туда этот код. Он полностью расписан в комментариях.

#импортируем библиотеку requests import requests #создаем функцию get_address_from_coords с параметром coords, куда мы будем посылать координаты и получать готовый адрес. def get_address_from_coords(coords): #заполняем параметры, которые описывались выже. Впиши в поле apikey свой токен! PARAMS = { "apikey":"ТОКЕН", "format":"json", "lang":"ru_RU", "kind":"house", "geocode": coords } #отправляем запрос по адресу геокодера. try: r = requests.get(url="https://geocode-maps.yandex.ru/1.x/", params=PARAMS) #получаем данные json_data = r.json() #вытаскиваем из всего пришедшего json именно строку с полным адресом. address_str = json_data["response"]["GeoObjectCollection"]["featureMember"][0]["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["AddressDetails"]["Country"]["AddressLine"] #возвращаем полученный адрес return address_str except Exception as e: #если не смогли, то возвращаем ошибку return "error" if __name__ == '__main__': #даем запрос на получение адреса с координатами 37.617585, 55.751903 address_str = get_address_from_coords("37.617585,55.751903") #распечатываем адрес print(address_str)

3) В консоли (терминале) переходим в папку с нашим файлом через команду «cd» (у меня он лежит в папке Documents/Python/).

И запускаем файл с помощью «python3».

Как результат, ты получишь адрес координат из кода.

Мы почти закончили! Осталось совсем немного.

Программируем Telegram бота на Python

Здесь в целом всё точно также, как и в предыдущей части.

Нам необходимо:

  • Установить библиотеку python-telegram-bot для управления нашим ботом.
  • Написать немного кода.

Поехали!

Установка библиотеки python-telegram-bot

1) Снова открывай консоль (терминал) и устанавливай python-telegram-bot с помощью команды:

pip install python-telegram-bot

Подробнее тут.

2) Пришло время написать код нашего бота. Я снова всё опишу в комментариях (не забудь поставить токен геокодера и токен бота в нужных местах в коде)!

#Подлкючаем библиотеку requests import requests #Подключаем нужные для бота модули из библиотеки telegram.ext from telegram.ext import Updater, CommandHandler, MessageHandler, Filters #это наша функция для получения адреса по координатам. С ней мы знакомы. def get_address_from_coords(coords): PARAMS = { "apikey": "ТОКЕН_ГЕОКОДЕРА", "format": "json", "lang": "ru_RU", "kind": "house", "geocode": coords } try: r = requests.get(url="https://geocode-maps.yandex.ru/1.x/", params=PARAMS) json_data = r.json() address_str = json_data["response"]["GeoObjectCollection"]["featureMember"][0]["GeoObject"]["metaDataProperty"][ "GeocoderMetaData"]["AddressDetails"]["Country"]["AddressLine"] return address_str except Exception as e: #единственное что тут изменилось, так это сообщение об ошибке. return "Не могу определить адрес по этой локации/координатам.\n\nОтправь мне локацию или координаты (долгота, широта):" #Эта функция будет использоваться когда человек первый нажал в боте START def start(update, context): #эта строка отправляет сообщение пользователю с просьбой послать локацию или координаты update.message.reply_text('Отправь мне локацию или координаты (долгота, широта):') #Эта функция будет использоваться, если пользователь послал в бота любой текст. #Мы ожидаем координаты, но если прийдет что-то другое не страшно, ведь мы описали в функции получения адреса возвращение ошибки в случае чего. def text(update, context): #получаем текст от пользователя coords = update.message.text #отправляем текст в нашу функцио получения адреса из координат address_str = get_address_from_coords(coords) #вовщращаем результат пользователю в боте update.message.reply_text(address_str) #Эта функция будет использоваться, если пользователь послал локацию. def location(update, context): #получаем обьект сообщения (локации) message = update.message #вытаскиваем из него долготу и ширину current_position = (message.location.longitude, message.location.latitude) #создаем строку в виде ДОЛГОТА,ШИРИНА coords = f"{current_position[0]},{current_position[1]}" #отправляем координаты в нашу функцию получения адреса address_str = get_address_from_coords(coords) #вовщращаем результат пользователю в боте update.message.reply_text(address_str) #Это основная функция, где запускается наш бот def main(): #создаем бота и указываем его токен updater = Updater("ТОКЕН_БОТА", use_context=True) #создаем регистратор событий, который будет понимать, что сделал пользователь и на какую функцию надо переключиться. dispatcher = updater.dispatcher #регистрируем команду /start и говорим, что после нее надо использовать функцию def start dispatcher.add_handler(CommandHandler("start", start)) #регистрируем получение текста и говорим, что после нее надо использовать функцию def text dispatcher.add_handler(MessageHandler(Filters.text, text)) #регистрируем получение локации и говорим, что после нее надо использовать функцию def location dispatcher.add_handler(MessageHandler(Filters.location, location)) #запускаем бота updater.start_polling() updater.idle() if __name__ == '__main__': #запускаем функцию def main main()

3) Создаем файл main_bot.py и сохраняем этот код в нём.

4) В консоли (терминале) переходим в папку с нашим файлом через команду «cd» (у меня он лежит в папке Documents/Python/).

5) И снова запускаем файл с помощью «python3». Теперь уже это файл нашего готового бота!

Всё! Заходи в своего бота в Telegram (ищи по нику) и используй🤩🥳.

Моего бота можно посмотреть тут @SayMyAddressBot.

P. S. Это моя первая инструкция на портале. Старался сделать так, чтобы было понятно даже совсем начинающим. Спасибо за то, что прочёл до конца!

{ "author_name": "Dan Kamilov", "author_type": "self", "tags": ["\u044d\u0442\u043e","\u044d\u0442\u0430","\u0441\u043e\u0437\u0434\u0430\u0435\u043c","\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c","\u0440\u0430\u0441\u043f\u0435\u0447\u0430\u0442\u044b\u0432\u0430\u0435\u043c","\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c","\u043f\u043e\u0434\u043b\u043a\u044e\u0447\u0430\u0435\u043c","\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c","\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c","\u043c\u044b","\u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c","\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c","\u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c","\u0435\u0441\u043b\u0438","\u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435","\u0434\u0430\u0435\u043c","\u0432\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0435\u043c","\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c","\u0432\u043e\u0432\u0449\u0440\u0430\u0449\u0430\u0435\u043c","selectel_\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f"], "comments": 6, "likes": 8, "favorites": 45, "is_advertisement": false, "subsite_label": "dev", "id": 156853, "is_wide": true, "is_ugc": true, "date": "Wed, 09 Sep 2020 12:35:49 +0300", "is_special": false }
(function () { let cdnUrl = `https://specialsf378ef5-a.akamaihd.net/SelectelBranding/images/` let previousArticleNumber = null let currentArticleNumber = 0 let platform = 'Desktop' let articles = [ // { // name: 'camera', // url: `${cdnUrl}CameraCat`, // text: 'умную камеру для\u00A0наблюдения за\u00A0котиками', // link: '1', // }, { name: 'chill', url: `${cdnUrl}ChillCat`, text: 'трекер, который подскажет, когда пора отдохнуть', link: 'https://vc.ru/promo/288561-eye-tracker', }, // { // name: 'cloud', // url: `${cdnUrl}CloudCat`, // text: 'котика: даёшь ему «пять», а\u00A0он делает бэкап в облако', // link: '3', // } ] let buttonCycle = document.querySelector('.button--cycle') let textField = document.querySelector('.selectel-footer-subtitle') let imageAgent = document.querySelector('.image--agent') let banner = document.querySelector('.selectel-footer') buttonCycle.addEventListener('click', cycleClick) let media = window.matchMedia("(max-width: 570px)") media.addEventListener('change', matchMedia) function matchMedia() { if (media.matches) { platform = 'Mobile' } else { platform = 'Desktop' } update() } matchMedia() function cycleClick(event) { if (event) { event.preventDefault() event.stopPropagation() } window.open('https://vc.ru/tag/selectelDIY', '_blank') //cycle(event) } function cycle(event) { // incrementArticleNumber() textField.innerHTML = generatedText() imageAgent.src = articles[currentArticleNumber].url + platform + '.svg?5' imageAgent.setAttribute("class", "") imageAgent.classList.add('image--agent', articles[currentArticleNumber].name) banner.href = articles[currentArticleNumber].link } function update() { banner.href = articles[currentArticleNumber].link imageAgent.src = articles[currentArticleNumber].url + platform + '.svg?5' textField.innerHTML = generatedText() } function incrementArticleNumber() { previousArticleNumber = currentArticleNumber if (currentArticleNumber >= articles.length - 1) { currentArticleNumber = 0 } else { currentArticleNumber++ } } function generatedText() { let defaultText if (platform === 'Desktop') { defaultText = `Мы тут собрали %text%. Хотите почитать?` } else { defaultText = `Мы тут собрали %text%.` } return defaultText.replace('%text%', articles[currentArticleNumber].text) } function getRandom(min, max) { min = Math.ceil(min) max = Math.floor(max) return Math.floor(Math.random() * (max - min + 1)) + min } (function create() { currentArticleNumber = getRandom(0, articles.length - 1) cycle() let page = document.querySelector('.page--entry') if (page) { function insertAfter() { let parents = page.querySelectorAll('[data-id="7"]') let referenceNode = parents[0] referenceNode.parentNode.insertBefore(banner, referenceNode.nextSibling); loaded() } setTimeout(() => insertAfter(), 0) } }()) function loaded() { banner.classList.add('loaded') } loadImages([ `${cdnUrl}CameraCatDesktop.svg`, `${cdnUrl}ChillCatDesktop.svg`, `${cdnUrl}CloudCatDesktop.svg`, `${cdnUrl}CameraCatMobile.svg`, `${cdnUrl}ChillCatMobile.svg`, `${cdnUrl}CloudCatMobile.svg`, ]) function loadImages(urls) { return Promise.all(urls.map(function (url) { return new Promise(function (resolve) { var img = document.createElement('img'); img.onload = resolve; img.onerror = resolve; img.src = url; }); })); } }())
0
6 комментариев
Популярные
По порядку
Написать комментарий...

Начну с вопроса - а зачем такой бот нужен? Любая онлайн карта без проблем справляется с определением адреса по координатам.
Конечно можно сказать, что это pet project и основной смысл в обучении, но зачем это тогда постить? Статья видимо рассчитана на крайне узкую прослойку начинающих программистов, которые уже вроде что-то умеют, но ещё не написали ни одного полноценного скрипта, который бы выполнял какую-то полезную функцию. 
Автор явно сам является начинающим программистом, а уже хочет научить чему-то других. Причём библиотека для работы с api телеги используется далеко не самая топовая, но в этом ничего плохого нет - как говорится на вкус и цвет.
Собственно я клоню к тому, что если автор хочет начать постить статьи о программировании, и сам при этом является начинающим программистом, то стоило начать с цикла статей с соответствующей тематикой, а-ля "Я являюсь программистом такого-то уровня и поставил перед собой задачу достичь такой-то цели. Буду рад советам в комментариях".
Крайне простой и (без обид, но сам понимаешь) абсолютно бесполезный тг-бот, коих сотни тысяч, а то и миллионы, с очень узкой специализацией конечно не тянет на такую цель.
А что тянет?, - Ну например было бы гораздо круче, если был выбран такой функционал бота, в котором нужно задействовать базы данных. И которого потом можно было бы интегрировать с сайтом или мобильным приложением.
В любом случае я не пытаюсь критиковать автора и уж тем более не хочу обидеть. Просто хотелось бы увидеть более осмысленный и интересный материал в этой области, а не подобное ребячество. Это было бы полезно, как для самого автора, так и для всех читателей.

3

Привет! Спасибо за критику. Пост в рамках конкурса для начинающих. Можешь посмотреть наши работы https://t.me/EngJackBot, https://t.me/OzyBot, https://t.me/ArzonAptekaBot. Но расписать создание таких ботов по простому - сложновато (да и только "профи" поймут всё), поэтому хотел скорее для широкой аудитории, чтобы побольше ребят не уходили расстроенные, а пробовали и понимали, что все возможно).

А бот из статьи используют уже несколько компаний для получения адреса. Т.к им клиенты скидывают локации (у водителей гонит интернет и навигатор не открывается, в регионах с плохим интернетом это боль) и многие не могут или забывают назвать точный адрес. При этом множество мелких бизнесов работают именно через Телеграм. Не все диджитализированы по максимуму;) ред.

3

Какая сейчас топовая библиотека для тг-бота и чем плоха эта библиотека?

0

Все очень четко и просто объяснили. Спасибо! 

1

Ещё бы с фотки координаты мог сканировать )

1

Рай закладчика

0

Комментарий удален

Читать все 6 комментариев
О Яндекс.Телефоне перед выходом электроники от Яндекс

На фоне оптимистичных новостей о том, что Яндекс готовится выйти на рынок бытовой техники и электроники хочется вспомнить их главную победу — Яндекс.Телефон.

За 100 лет до МММ: как рязанский банкир построил финансовую пирамиду в 19 веке и обманул вкладчиков на 12 млн рублей Статьи редакции

Когда в скопинском банке оказалось недостаточно денег, чтобы выплачивать проценты по вкладам, директор Иван Рыков «нарисовал» баланс и привлёк новых вкладчиков. На их деньги он отдавал проценты — так и зародилась первая в России финансовая пирамида, которая просуществовала 15 лет.

Здание Скопинского банка Архив Скопинского исторического общества
Как мы проводили командную ретроспективу в Minecraft

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

vavada bbc Вавада вход + регистрация - зеркало на официальный сайт

Vavada — онлайн , предлагающее огромный ассортимент азартных развлечений, выгодные бонусы, интересные акции. Гостям доступны удобные способы пополнения

Эксперты Httpool выступят на конференции по глобальному маркетингу Globalize! 2021

Событие соберет самых продвинутых специалистов в сфере трафика и аналитики из Google, Httpool, AppsFlyer, Aitarget, Angle Connect, TikTok, OWOX, SHAREit, Tribuna, SportQuake, LCFC, FBS.

Раскручивают на анализы и навязывают «абонемент» к врачу: как и почему клиники монетизируют тревожность родителей

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

Заголовок вышел из-под контроля
Нужны ли в России сити-фермы

И появятся ли грядки на крышах пятиэтажек.

re-thinkingthefuture.com
Что за чудеса происходят с алгоритмами «Яндекс.Директ» в РСЯ. Почему испортилась РСЯ и как это исправить

Многие рекламодатели «Яндекс.Директ» начиная с лета 2021-го года заметили странные тенденции в работе нейросети РСЯ. Я в их числе. Что делать, если рекламные кампании резко перестали приносить конверсии и засоряют сайт некачественным трафиком за ваши деньги?

Готовы выбрать победителя премии «Экспортер года eBay — 2021»?
Как традиционному малому бизнесу превратиться в стартап: план действий

Сейчас в России предприниматели переходят из традиционного малого бизнеса в стартапы очень редко — меньше чем в 0,02% случаев. Это не больше 1 000 стартапов из около 6 млн предприятий малого бизнеса. Поговорим о том, что мешает предпринимателям и как действовать, если есть желание создать стартап.

null