• Как парсить сайт Metro-CC.ru на python через selenium?

    @SwitcherN Автор вопроса
    Начинаю изучать python
    Проблему решил. Нашел хорошую статью на habr'е. Главный посыл - старайтесь найти api, если он есть. Это будет самый верный путь к решению проблемы. BeautifulSoup, Selenium - как крайние меры.

    Что касается сайта Metro C&C - перехватил XHR-запрос graph. По нему парсится JSON. Пока - по конкретному магазину, дальше надо будет циклом прогнать интересующие магазины. Отдает JSON на 30 продуктов, но можно в data запроса изменить параметр size. Изменил в своем запросе на 2 000. По разным магазинам от 800 до 1100 элементов отдает - в зависимости от матрицы магазина.
    Плюсом в data можно почистить структуру получаемого JSON'а. Ниже 2 примера.

    Код запроса
    import json
    import requests
    
    cookies = {
        'metro_api_session': 'TVrehtvJIsAlrrmi73LSZ1td5cF4hHucbGsxIzM5',
        '_ga_VHKD93V3FV': 'GS1.1.1703784480.1.1.1703784576.0.0.0',
        'tmr_lvid': 'c6ca40446fcd9234ed280196bdd2bab2',
        'tmr_lvidTS': '1703784486767',
        '_gcl_au': '1.1.1217202258.1703784484',
        '_ym_visorc': 'b',
        '_ym_d': '1703784483',
        '_ym_isad': '2',
        '_ym_uid': '1703784483244081529',
        'uxs_uid': '740bab20-a5a6-11ee-b876-db689cf62a64',
        'mp_88875cfb7a649ab6e6e310368f37a563_mixpanel': '%7B%22distinct_id%22%3A%20%22%24device%3A18cb1780127150a-0d62ba868fe2ce-3d62684b-16a7f0-18cb1780128150a%22%2C%22%24device_id%22%3A%20%2218cb1780127150a-0d62ba868fe2ce-3d62684b-16a7f0-18cb1780128150a%22%2C%22%24initial_referrer%22%3A%20%22%24direct%22%2C%22%24initial_referring_domain%22%3A%20%22%24direct%22%7D',
        '_ga': 'GA1.1.878068636.1703784481',
        '_slfreq': '633ff97b9a3f3b9e90027740%3A633ffa4c90db8d5cf00d7810%3A1703791681%3B64a81e68255733f276099da5%3A64abaf645c1afe216b0a0d38%3A1703791681',
        'directCrm-session': '%7B%22deviceGuid%22%3A%2297972bdb-a82e-4f8d-a11a-24ff81485078%22%7D',
        'mindboxDeviceUUID': '97972bdb-a82e-4f8d-a11a-24ff81485078',
        '_slfs': '1703784479362',
        '_slid': '658db01f4dc372cd800a100c',
        '_slsession': '2953AFDF-D8E0-4CE4-9DC7-CED951138786',
    }
    
    headers = {
        'Accept': 'application/json, text/plain, */*',
        'Content-Type': 'application/json',
        'Origin': 'https://online.metro-cc.ru',
        'Content-Length': '4669',
        'Accept-Language': 'ru',
        'Host': 'api.metro-cc.ru',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Safari/605.1.15',
        'Referer': 'https://online.metro-cc.ru/',
        'Accept-Encoding': 'gzip, deflate, br',
        'Connection': 'keep-alive',
    }
    
    data = '{"query":"\\n query Query($storeId: Int!, $slug: String!, $attributes:[AttributeFilter], $filters: [FieldFilter], $from: Int!, $size: Int!, $sort: InCategorySort, $in_stock: Boolean, $eshop_order: Boolean, $is_action: Boolean, $price_levels: Boolean) {\\n category (storeId: $storeId, slug: $slug, inStock: $in_stock, eshopAvailability: $eshop_order, isPromo: $is_action, priceLevels: $price_levels) {\\n id\\n name\\n slug\\n id\\n parent_id\\n meta {\\n description\\n h1\\n title\\n keywords\\n }\\n disclaimer\\n description {\\n top\\n main\\n bottom\\n }\\n# treeBranch {\\n# id\\n# name\\n# slug\\n# children {\\n# category_type\\n# id\\n# name\\n# slug\\n# children {\\n# category_type\\n# id\\n# name\\n# slug\\n# children {\\n# category_type\\n# id\\n# name\\n# slug\\n# children {\\n# category_type\\n# id\\n# name\\n# slug\\n# }\\n# }\\n# }\\n# }\\n# }\\n breadcrumbs {\\n category_type\\n id\\n name\\n parent_id\\n parent_slug\\n slug\\n }\\n promo_banners {\\n id\\n image\\n name\\n category_ids\\n virtual_ids\\n type\\n sort_order\\n url\\n is_target_blank\\n analytics {\\n name\\n category\\n brand\\n type\\n start_date\\n end_date\\n }\\n }\\n\\n\\n dynamic_categories(from: 0, size: 9999) {\\n slug\\n name\\n id\\n category_type\\n }\\n filters {\\n facets {\\n key\\n total\\n filter {\\n id\\n name\\n display_title\\n is_list\\n is_main\\n text_filter\\n is_range\\n category_id\\n category_name\\n values {\\n slug\\n text\\n total\\n }\\n }\\n }\\n }\\n total\\n prices {\\n max\\n min\\n }\\n pricesFiltered {\\n max\\n min\\n }\\n products(attributeFilters: $attributes, from: $from, size: $size, sort: $sort, fieldFilters: $filters) {\\n health_warning\\n limited_sale_qty\\n id\\n slug\\n name\\n name_highlight\\n article\\n main_article\\n main_article_slug\\n is_target\\n category_id\\n url\\n images\\n pick_up\\n rating\\n icons {\\n id\\n badge_bg_colors\\n rkn_icon\\n caption\\n image\\n type\\n is_only_for_sales\\n stores\\n caption_settings {\\n colors\\n text\\n }\\n stores\\n sort\\n image_png\\n image_svg\\n description\\n end_date\\n start_date\\n status\\n }\\n manufacturer {\\n id\\n image\\n name\\n }\\n packing {\\n size\\n type\\n pack_factors {\\n instamart\\n }\\n }\\n stocks {\\n value\\n text\\n eshop_availability\\n scale\\n prices_per_unit {\\n old_price\\n offline {\\n price\\n old_price\\n type\\n offline_discount\\n offline_promo\\n }\\n price\\n is_promo\\n levels {\\n count\\n price\\n }\\n online_levels {\\n count\\n price\\n discount\\n }\\n discount\\n }\\n prices {\\n price\\n is_promo\\n old_price\\n offline {\\n old_price\\n price\\n type\\n offline_discount\\n offline_promo\\n }\\n levels {\\n count\\n price\\n }\\n online_levels {\\n count\\n price\\n discount\\n }\\n discount\\n }\\n }\\n }\\n }\\n }\\n","variables":{"storeId":12,"sort":"default","size":30,"from":0,"filters":[{"field":"main_article","value":"0"}],"attributes":[],"in_stock":false,"eshop_order":false,"allStocks":false,"slug":"vino"}}'
    
    response = requests.post('https://api.metro-cc.ru/products-api/graph', headers=headers, cookies=cookies, data=data)
    with open('metro.json', 'w') as file:
        json.dump(response.json(), file, indent=4, ensure_ascii=False)</spoiler>


    Оптимизирвоанный код запроса
    import json
    import requests
    
    cookies = {
        'metro_api_session': 'TVrehtvJIsAlrrmi73LSZ1td5cF4hHucbGsxIzM5',
        '_ga_VHKD93V3FV': 'GS1.1.1703784480.1.1.1703784576.0.0.0',
        'tmr_lvid': 'c6ca40446fcd9234ed280196bdd2bab2',
        'tmr_lvidTS': '1703784486767',
        '_gcl_au': '1.1.1217202258.1703784484',
        '_ym_visorc': 'b',
        '_ym_d': '1703784483',
        '_ym_isad': '2',
        '_ym_uid': '1703784483244081529',
        'uxs_uid': '740bab20-a5a6-11ee-b876-db689cf62a64',
        'mp_88875cfb7a649ab6e6e310368f37a563_mixpanel': '%7B%22distinct_id%22%3A%20%22%24device%3A18cb1780127150a-0d62ba868fe2ce-3d62684b-16a7f0-18cb1780128150a%22%2C%22%24device_id%22%3A%20%2218cb1780127150a-0d62ba868fe2ce-3d62684b-16a7f0-18cb1780128150a%22%2C%22%24initial_referrer%22%3A%20%22%24direct%22%2C%22%24initial_referring_domain%22%3A%20%22%24direct%22%7D',
        '_ga': 'GA1.1.878068636.1703784481',
        '_slfreq': '633ff97b9a3f3b9e90027740%3A633ffa4c90db8d5cf00d7810%3A1703791681%3B64a81e68255733f276099da5%3A64abaf645c1afe216b0a0d38%3A1703791681',
        'directCrm-session': '%7B%22deviceGuid%22%3A%2297972bdb-a82e-4f8d-a11a-24ff81485078%22%7D',
        'mindboxDeviceUUID': '97972bdb-a82e-4f8d-a11a-24ff81485078',
        '_slfs': '1703784479362',
        '_slid': '658db01f4dc372cd800a100c',
        '_slsession': '2953AFDF-D8E0-4CE4-9DC7-CED951138786',
    }
    
    headers = {
        'Accept': 'application/json, text/plain, */*',
        'Content-Type': 'application/json',
        'Origin': 'https://online.metro-cc.ru',
        'Content-Length': '4669',
        'Accept-Language': 'ru',
        'Host': 'api.metro-cc.ru',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Safari/605.1.15',
        'Referer': 'https://online.metro-cc.ru/',
        'Accept-Encoding': 'gzip, deflate, br',
        'Connection': 'keep-alive',
    }
    
    shop_id = "26"
    data = f'{{"query":"\\n query Query($storeId: Int!, $slug: String!, $attributes:[AttributeFilter], $filters: [FieldFilter], $from: Int!, $size: Int!, $sort: InCategorySort, $in_stock: Boolean, $eshop_order: Boolean, $is_action: Boolean, $price_levels: Boolean) {{\\n category (storeId: $storeId, slug: $slug, inStock: $in_stock, eshopAvailability: $eshop_order, isPromo: $is_action, priceLevels: $price_levels) {{\\n id\\n name\\n slug\\n id\\n parent_id\\n# treeBranch {{\\n# id\\n# name\\n# slug\\n# children {{\\n# category_type\\n# id\\n# name\\n# slug\\n# children {{\\n# category_type\\n# id\\n# name\\n# slug\\n# children {{\\n# category_type\\n# id\\n# name\\n# slug\\n# children {{\\n# category_type\\n# id\\n# name\\n# slug\\n# }}\\n# }}\\n# }}\\n# }}\\n# }}\\n products(attributeFilters: $attributes, from: $from, size: $size, sort: $sort, fieldFilters: $filters) {{\\n id\\n slug\\n name\\n name_highlight\\n article\\n main_article\\n main_article_slug\\n is_target\\n category_id\\n url\\n images\\n pick_up\\n rating\\n manufacturer {{\\n id\\n image\\n name\\n }}\\n packing {{\\n size\\n type\\n pack_factors {{\\n instamart\\n }}\\n }}\\n stocks {{\\n value\\n text\\n eshop_availability\\n scale\\n prices_per_unit {{\\n old_price\\n price\\n is_promo\\n discount\\n }}\\n }}\\n }}\\n }}\\n }}\\n","variables":{{"storeId":{shop_id},"sort":"default","size":2000,"from":0,"filters":[{{"field":"main_article","value":"0"}}],"attributes":[],"in_stock":false,"eshop_order":false,"allStocks":false,"slug":"vino"}}}}'
    
    
    response = requests.post('https://api.metro-cc.ru/products-api/graph', headers=headers, cookies=cookies, data=data)
    with open('metro.json', 'w') as file:
        json.dump(response.json(), file, indent=4, ensure_ascii=False)
    Ответ написан
    Комментировать
  • Обработка нажатия кнопки в телеграмм боте?

    @SwitcherN
    Начинаю изучать python
    Во-первых, надо определиться каким образом вы выводите кнопку - от этого отличаются методы обработки событий.

    Есть два вида кнопок - это кастомной клавиатура, которая заменяет собой стандартную клавиатуру, либо онлайн кнопки - выводятся под сообщением. Для того и другого варианта не забудь импортировать библиотеку:

    from telebot import types

    1. Генерация кастомной клавиатуры.

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

    keyboard = utilits.generate_keyboard('Сделать заказ', 'Хочу скидку на заказ', 'Изменить персональную информацию')
    bot.send_message(message.chat.id, msg, reply_markup=keyboard)


    Тут создаем keyboard с помощью функции generate_keyboard, которая у меня лежит в файле utilits. Передаем в качестве аргументов то, что должно быть написано на кнопках.

    Сама функция generate_keyboard:

    def generate_keyboard (*answer):
        keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True)
        for item in answer:
            button = types.KeyboardButton(item)
            keyboard.add(button)
        return keyboard


    Здесь вызываем метод ReplyKeyboardMarkup из библиотеки types. Дальше проходимся итеративно по полученным аргументам и генерируем кнопки попутно добавляя кнопки к клавиатуре - keyboard.add(button).
    Возвращаем собранную клавиатуру.

    Далее обрабатываем полученный ответ. Я для обработки полученного ответа придумал следующий костыль - статус каждого клиента, который храню вместе с его ID в базе данных. Статус - по сути место каждого клиента на пути к оформлению заказа:

    @bot.message_handler(content_types=["text"])
    def check_text_message(message):
        status = int()
        try:
            status = config.current_users[message.chat.id][0]
        except Exception as er:
            status = 0
        if status == 0:
            bot.send_message(message.chat.id, 'Извините, я запутался. Давайте начнем сначала')
            first_step(message)
        elif status == 10:
            if message.text == 'Сделать заказ':
                Dialogs.order(message) ...


    То есть проверяю статус - "elif status == 10:"
    Если мы тут и получаем ответ "Сделать заказ", то выводим следующее сообщение, которое генерируем с помощью функции order - "Dialogs.order(message)". Эта же функция у меня и меняет статус, сохраняя его по пути в БД, на случай если бот "ляжет" и забудет кто на каком этапе находиться.

    2. Генерация онлайн клавиатуры.

    Все очень походе. Вот так генерирую такой тип клавиатуры, но тут необходимо помимо надписи на самой кнопке задать еще и команду, по которой мы и будем событие обрабатывать дополнительно (callback_data):

    keyboard = utilits.generate_inline_keyboard(['Имя', 'change_name'],
                                                     ['Телефон', 'change_phone'],
                                                     ['️Адрес', 'change_adress'],
                                                     ['Вернуться обратно', 'back'])


    def generate_inline_keyboard (*answer):
        keyboard = types.InlineKeyboardMarkup()
        temp_buttons = []
        for i in answer:
            temp_buttons.append(types.InlineKeyboardButton(text=i[0], callback_data=i[1]))
        keyboard.add(*temp_buttons)
        return keyboard


    А это обработка событий. Тут проще, можно обрабатывать не через статус, а по конкретной callback_data:

    @bot.callback_query_handler(func=lambda call: True)
    def ans(call):
        try:
            message = call.message
            if call.data == 'change_name':
                Dialogs.change_name(message)
            elif call.data == 'change_phone': ...
    Ответ написан
    Комментировать
  • Почему Instagram обрезает видео по времени?

    @SwitcherN
    Начинаю изучать python
    Потому что это правило Инстаграмм. Видео в посте максимум 60 секунд. В сториз - 15 секунд.
    Ответ написан
    Комментировать
  • Номер строки, содержащей максимальное число одинаковых элементов?

    @SwitcherN
    Начинаю изучать python
    Могу предложить немного другой вариант. Можно каждую строчку запихать в set(). Тогда строчка, которая имеет минимальную длину (минимальное число уникальных значений) искомая. То есть set(matrix[1]) вернет (9,5,1,8), а set(matrix[4]) вернет (6, 3, 7).

    min_unique_num = M # Задаем стартовое минимальное значение уникальных чисел в строчке равной длине строки
    searching_row = int() #Переменная, куда будем писать номер строки с наибольшим количеством повторов
    
    for i in range(0, M):
        if len(set(matrix[i])) < unique_num_in_row: # Если количество уникальных элементов в строке меньше, чем во всех предыдущих, то...
            unique_num_in_row = len(set(matrix[i])) # Пишем новое минимальное значение в переменную
            searching_row = i # Запоминаем номер строки как искомый
    
    return searching_row # Возвращаем номер строки, либо можно вернуть саму строку matrix[searching_row]
    Ответ написан
    Комментировать
  • Как пересылать информацию отправленную боту другому пользователю?

    @SwitcherN
    Начинаю изучать python
    Очень много вопросов, которые можно заменить одним - "Сможете написать код за меня?".

    Немного помогу, натолкнув на варианты решения. Это не панацея, но я бы решал задачу этими методами.

    1. Этот код я бы заменил на такой формат:
    bot.reply_to(message, "Привет Что хочешь поесть? \n\n Мануал  ", reply_markup=markup_menu )

    на такой:
    bor.send_message(message.chat.id, "Привет Что хочешь поесть? \n\n Мануал  ", reply_markup=markup_menu )

    Будет выглядеть как просто сообщение, а не ответ с постоянным цитированием предыдущего сообщения.

    2. Можно сделать отдельную функцию генерации клавиатуры. Например:
    def generate_keyboard (*answer):
        keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True)
        for item in answer:
            keyboard.add(item)
        return keyboard

    Тогда генерация любой клавиатуры с последующим отправлением её пользователю выглядит так:
    msg = 'Тут будет твое сообщение.' # Сообщение, которое будем отправлять
    keyboard = generate_keyboard('Кнопка 1', 'Кнопка 2', 'Кнопка 3') #Генерируем клавиатуру
    bot.send_message(message.chat.id, msg, reply_markup=keyboard) #Отправляем сообщение и клавиатуру


    3. Для того, чтобы собрать информацию от пользователя и отправить сотруднику можно использовать словарь. Например, словарь может выглядеть следующим образом:
    users_orders = {user_chat_id:{eating:breakfast, question:"Что тут происходит вообще?"}}

    И тогда запись информации будет происходить при получении ответа. Пример:
    if  message.text == "Хочу позавтракать":
        users_orders[message.chat.id][eating] = breakfast
        keyboard = generate_keyboard('Вариант 1', 'Вариант 2', 'Вариант 3')
        bot.send_message(message.chat.id, 'Выберите завтрак', reply_markup=keyboard )


    4. Когда всю информацию получил - отправляем сотруднику ответ на основании сформированного словаря и удалим клавиатуру:
    if message.text == "Завершить":
        hide_keyboard = types.ReplyKeyboardRemove()
        bot.send_message(message.chat.id, 'Ваш запрос принят, обработка займет не более 5 мин', reply_markup=hide_keyboard)
        msg = " От клиента {} поступил заказ:\n{}.\nИ вопрос:\n" \
        "{}".format(message.chat.id, users_orders[message.chat.id][eating], users_orders[message.chat.id][question])
        bot.send_message('841260346', msg)


    Данные необходимо дополнительно сохранять в БД. Иначе после рестарта вся информация будет удалена.
    Ответ написан
    Комментировать
  • Как пересылать сообщения пользователя отправленные боту другому пользователю?

    @SwitcherN
    Начинаю изучать python
    Небольшой пример:

    bot = telebot.TeleBot('Тут должен быть твой токен')
    
    
    @bot.message_handler(content_types=["text"]) # Тут ловим все текстовые сообщения от пользователя
    def some_funtion(message): #Название функции неважно
        bot.send_message('ID чата пользователя, которому необходимо сообщение переслать', message.text)


    То есть метод send_message принимает 2 позиционных аргумента. Первый - это ID чата с пользователем, кому вывести сообщение. Второй аргумент - текст пересылаемого сообщения. Можно чуть доработать и заменить строку следующим:

    ...
    msg = "Пользователь {} написал \"{}\".".format(message.from_user.username, message.text)
    bot.send_message('ID чата пользователя, которому необходимо сообщение переслать', msg)
    ...


    На выходе получим сообщение вида: Пользователь Someone написал "Привет! Как дела?".

    ID чата можно получить с помочью небольшой функции, которая присылает сообщение:

    @bot.message_handler(commands=["id"]) # Получить ID чата при отправке сообщения /id
    def chat_id(message):
        my_chat_id = int(message.chat.id)
        bot.send_message(message.chat.id, my_chat_id)


    P.S. Но вообще - начни хотя бы отсюда: https://groosha.gitbooks.io/telegram-bot-lessons/.
    Ответ написан
    3 комментария
  • Как получить telegra.ph access_token?

    @SwitcherN
    Начинаю изучать python
    Напиши @BotFather

    UPD: Неверно понял вопрос.

    Теперь пару выдержек из API.

    All queries to the Telegraph API must be served over HTTPS and should be presented in this form: https://api.telegra.ph/%method%.

    createAccount
    Use this method to create a new Telegraph account. Most users only need one account, but this can be useful for channel administrators who would like to keep individual author names and profile links for each of their channels. On success, returns an Account object with the regular fields and an additional access_token field.

    access_token (String)
    Optional. Only returned by the createAccount and revokeAccessToken method. Access token of the Telegraph account.

    Короче, отправляй запрос вида:

    Sample request
    https://api.telegra.ph/createAccount?short_name=Sa...

    Где меняешь Sandbox и Anonymous на свои данные.
    В ответ получишь токен.
    Ответ написан
    1 комментарий
  • Где научиться алгоритмам?

    @SwitcherN
    Начинаю изучать python
    Сейчас читаю "Грокаем алгоритмы", как советовали выше. Но по мне, ни разу не математику и не программисту, очень уж примитивно.
    До этого смотрел на youtube лекции курск лекций "Алгоритмы на Python 3" от Хирьянова Тимофея Фёдоровича (МФТИ). Мне "зашло". Так как "для себя" начал учить python, то тут просто 2-в-1 - и основы синтаксиса, и алгоритмы.
    Ответ написан
    Комментировать
  • Как обновить кастомную клавиатуру в телеграм?

    @SwitcherN
    Начинаю изучать python
    При отправке любого сообщения можно обновить клавиатуру.

    bot = telebot.TeleBot(token)
    
    keyboard = types.ReplyKeyboardMarkup()
    bot.send_message(message.chat.id, 'Сообщение', reply_markup=keyboard)


    Остается отправить всем пользователям сообщение с новой клавиатурой. Например, собрать все chat_id текущих пользователей в список users_list и:

    @bot.message_handler(commands=["new_keyboard_for_all_users"])
    def send_new_keyboard (message):
        keyboard = types.ReplyKeyboardMarkup() # Новая клавиатура
        for user in users_list:
            bot.send_message(user, 'Произвольное сообщение', reply_markup=keyboard)
    Ответ написан
    1 комментарий
  • Как при нажатии кнопки НАЗАД выполнить определенную команду?

    @SwitcherN
    Начинаю изучать python
    bot = telebot.TeleBot(config.token)
    
    ...
    
    @bot.message_handler(content_types=["text"]) # Обрабатываем все сообщения типа "текст". Нажатие кнопки == отправка сообщения с тектом кнопки.
    def check_text_message(message): # Имя функции может быть любое
        if message.text == "Назад": # Эмоджи со стрелкой вставить не даёт, но надо чтобы проверяемое сообщение в точности было равно надписи на кнопке
            do_something (message) # Аргумент передаем, если надо что-либо сделать с сообщением, например, отправить ответ
    Ответ написан
    Комментировать
  • Можно ли запустить telegram бота без нажатия кнопки start?

    @SwitcherN
    Начинаю изучать python
    Отправить сообщение «/start».

    Воспринимается как команда, обрабатывается соответствующим образом.
    Ответ написан
  • Как узнать username пользователя по его ID в телеграм-боте?

    @SwitcherN
    Начинаю изучать python
    При получении message:

    message.from_user.id
    message.from_user.first_name
    message.from_user.last_name
    message.from_user.username
    Ответ написан
    Комментировать
  • Как передать список городов в bot.send_message?

    @SwitcherN
    Начинаю изучать python
    Как вариант:

    city_list = [1, 2, 3 ...]
    
    for city in city_list:
        city_list_to_string += city + '\n'
    
    msg = 'Вас приветствует магазин\n'
    u'Хороших покупок.\n'
    u'➖➖➖➖➖➖➖➖➖➖\n\n'
    u'Для получения помощи нажмите ? /help\n'
     u'Выберите город из списка:\n'
     u'➖➖➖➖➖➖➖➖➖➖\n'
    u' Здесь надо вывести список городов\n'
    u'[ Нажмите  {} ]\n'
     u'➖➖➖➖➖➖➖➖➖➖\n' .format(city_list_to_string)
    bot.send_message (message.chat.id, msg)
    Ответ написан
    Комментировать
  • Как вытянуть ответ пользователя телеграмм боту и добавить его в переменную типа string?

    @SwitcherN
    Начинаю изучать python
    Добавь обработчик поступающих текстовых сообщений:

    @bot.message_handler(content_types=["text"])
    def i_read_your_message (message): #название функции не имеет значение
        if message.text == "Голосіївський":
            #do_something
        elif message.text == "Дарницький":
            #do_something_else


    Можно делать клавиатуру в виде InlineKeyboard (то есть выводится не вместо родной клавиатуру, а прямо под сообщением в окне чата). Там обратка несколько другая. Если надо - напишу пример.

    Есть еще вариант регистрировать введеный текст, а нажатие кнопки == вводу просто текста, который написан на кнопке, через метод
    .register_next_step_handler ("сообщение на которое реагируем", "функция, которая обрабатывает ответ").

    Но у меня "не заводится". Вопрос задал тут, но пока ответа нет.
    Ответ написан
    Комментировать