Я использую библиотеку Playwright для асинхронного запуска нескольких сессий и aiogram 3 для получения данных через телеграм-бота. Я пытаюсь реализовать процесс входа на сайт через SMS-код. Для этого мне нужно сначала вызвать функцию, которая запрашивает у пользователя номер телефона, затем в следующей функции обработать этот номер, после чего получить SMS-код от пользователя и в другой функции с помощью состояния обработать его и ввести на сайте. Я не знаю, как в Playwright реализовать ожидание и последующую отправку SMS-кода. Можете помочь с этой задачей?
Конечно! Чтобы передать данные между функциями в Playwright и использовать их в асинхронном контексте, вы можете воспользоваться несколькими подходами. Я расскажу о простом подходе, используя замыкания и асинхронные функции. ### Пример реализации Предположим, у вас есть несколько функций: одна для запроса номера телефона, вторая для отправки SMS-кода, и третья для ввода кода на сайте. Мы можем использовать замыкания, чтобы передавать данные между этими функциями. ```python import asyncio from playwright.async_api import async_playwright from aiogram import Bot, Dispatcher, types # Инициализация бота API_TOKEN = 'YOUR_API_TOKEN' bot = Bot(token=API_TOKEN) dp = Dispatcher(bot) # Глобальная переменная для хранения номера телефона и SMS-кода user_data = {'phone_number': None, 'sms_code': None} # Функция для запроса номера телефона async def request_phone_number(chat_id): await bot.send_message(chat_id, "Введите ваш номер телефона:") # Здесь можно ожидать ответа пользователя # Используем состояние для обработки - пример с использованием aiogram @dp.message_handler(lambda message: message.from_user.id == chat_id) async def receive_phone_number(message: types.Message): user_data['phone_number'] = message.text await bot.send_message(chat_id, "Введите SMS-код:") await request_sms_code(chat_id) # Функция для запроса SMS-кода async def request_sms_code(chat_id): @dp.message_handler(lambda message: message.from_user.id == chat_id) async def receive_sms_code(message: types.Message): user_data['sms_code'] = message.text await process_login(chat_id) # Функция для входа async def process_login(chat_id): async with async_playwright() as p: browser = await p.chromium.launch() page = await browser.new_page() # Здесь логина на сайт await page.goto('http://example.com/login') # Ввод номер телефона и отправка await page.fill('input[name="phone"]', user_data['phone_number']) await page.click('button[type="submit"]') # Ввод SMS-кода и отправка await page.fill('input[name="sms_code"]', user_data['sms_code']) await page.click('button[type="submit"]') # Здесь вы можете продолжить обработку или проверить результаты входа await browser.close() # Запуск бота и логики async def main(): # Это может быть ваш обработчик команд /start в aiogram, например @dp.message_handler(commands=['start']) async def start_command(message: types.Message): await request_phone_number(message.from_user.id) await dp.start_polling() if __name__ == '__main__': asyncio.run(main()) ``` ### Объяснение кода: 1. **Глобальные переменные**: Я использую `user_data` для хранения номера телефона и SMS-кода. 2. **Асинхронные функции**: Каждая функция отвечает за определенный этап процесса. `request_phone_number` запрашивает номер телефона, `request_sms_code` — SMS-код, а `process_login` выполняет вход на сайт. 3. **Пока ожидаем ответа пользователя**: Используется `@dp.message_handler`, чтобы обрабатывать входящие сообщения от конкретного пользователя, и каждая функция подписывается на новое сообщение. 4. **Состояние бота**: В случае более сложной логики, вы можете использовать состояния в aiogram для управления диалогами. Этот подход позволяет хранить данные между асинхронными вызовами. Вы можете модифицировать пример, добавляя дополнительные проверки и обработку ошибок в зависимости от ваших требований.
Я разобрался кое-как, можно после создания страницы и браузера возвращать эти объекты из функции создании браузера и страницы, затем это объекты записывать в стейт (FSMContext) и уже после введенного кода делать вводить его на странице в стейте.
import asyncio from playwright.async_api import async_playwright from aiogram import Bot, Dispatcher, types from aiogram.contrib.fsm_storage.memory import MemoryStorage from aiogram.dispatcher import FSMContext from aiogram.dispatcher import State, StatesGroup API_TOKEN = 'YOUR_TELEGRAM_BOT_TOKEN' # Инициализация бота и диспетчера bot = Bot(token=API_TOKEN) storage = MemoryStorage() dp = Dispatcher(bot, storage=storage) # Определение состояний для FSM class Form(StatesGroup): waiting_for_phone = State() waiting_for_code = State() async def login_with_playwright(phone_number: str): async with async_playwright() as p: browser = await p.chromium.launch(headless=False) # Установите headless=True для запуска без GUI page = await browser.new_page() await page.goto('URL_ВАШЕГО_САЙТА') # Ввод номера телефона await page.fill('input[name="phone"]', phone_number) await page.click('button#send-code') # Замените селектор на ваш # Ждем, пока код придет (например, 30 секунд) await asyncio.sleep(30) # Увеличьте время ожидания, если нужно return page # Возвращаем страницу для дальнейшего использования @dp.message_handler(commands=['start']) async def cmd_start(message: types.Message): await Form.waiting_for_phone.set() await message.reply("Введите ваш номер телефона:") @dp.message_handler(state=Form.waiting_for_phone) async def process_phone(message: types.Message, state: FSMContext): phone_number = message.text await state.update_data(phone_number=phone_number) # Отправляем номер телефона на сайт и получаем страницу page = await login_with_playwright(phone_number) # После отправки номера сообщаем пользователю о необходимости ввести код await message.reply("Код был отправлен на ваш номер. Пожалуйста, введите его:") await state.update_data(page=page) # Сохраняем страницу в состоянии await Form.waiting_for_code.set() @dp.message_handler(state=Form.waiting_for_code) async def process_code(message: types.Message, state: FSMContext): user_data = await state.get_data() phone_number = user_data.get('phone_number') sms_code = message.text page = user_data.get('page') # Здесь можно добавить логику для ввода кода на сайте await page.fill('input[name="code"]', sms_code) # Замените селектор на ваш await page.click('button#submit-code') # Замените селектор на ваш await state.finish() await message.reply("Вы успешно вошли в систему!") if __name__ == '__main__': from aiogram import executor executor.start_polling(dp, skip_updates=True)