Узнайте, как автоматизировать еженедельную лотерею с помощью Python, Playwright и GitHub Actions. Полный разбор кода и архитектуры. Начните прямо сейчас!
Лето в Сан-Франциско — время концертов Stern Grove. Каждую неделю нужно не забыть зарегистрироваться в лотерее на бесплатные билеты. Вместо того чтобы ставить напоминание, я написал Python-скрипт, который запускается раз в неделю через GitHub Actions, парсит сайт фестиваля с помощью Playwright и автоматически участвует в лотерее. В этой статье я покажу, как это работает, и дам готовый код, который вы сможете адаптировать под свои задачи.
Проект состоит из нескольких модулей:
Вместо базы данных используется JSON-файл, который коммитится обратно в репозиторий после каждого запуска:
{
"entered": [
{
"event_id": "abc123",
"show": "Название концерта",
"entered_at": "2025-06-21T10:02:00Z"
}
]
}
Крон-задача запускает скрипт каждую неделю:
# .github/workflows/lottery.yml
on:
schedule:
- cron: "0 17 * * 1" # еженедельная проверка
workflow_dispatch:
Перед тем как писать код, важно изучить реальную структуру данных. Агент выполнил инспекцию объекта window.tixologiWidget.concerts на странице Stern Grove. Это позволило узнать точные названия полей, формат даты ISO 8601 и структуру ID события. Пример того, что было получено:
// Что реально выдает страница
window.tixologyWidget.concerts
// → [{ eventId, name, startDate: "2025-07-13T19:00:00Z", ... }]
Такой подход — проверка на реальных данных вместо предположений — разница между кодом, который работает с первого раза, и кодом, который падает в продакшене.
Функция commit_state не только читает JSON, но и после успешного участия коммитит и пушит изменения с помощью GitHub Personal Access Token (PAT):
def commit_state(token: str) -> None:
subprocess.run(["git", "add", "entered_lotteries.json"], check=True)
subprocess.run(["git", "commit", "-m", "Update entered lotteries"], check=True)
subprocess.run(["git", "push"], check=True)
Когда агент добавил notify.py, ревьюер-субагент сразу заметил две проблемы:
print() вместо модуля loggingОбе проблемы были исправлены до перехода к следующей задаче. Вот исправленный код:
import logging
logger = logging.getLogger(__name__)
resend.api_key = os.environ["RESEND_API_KEY"] # инициализируется один раз
def notify_success(show: str) -> None:
logger.info("Участие в лотерее для %s", show)
resend.Emails.send({...})
Первый реальный запуск провалился. Две проблемы с окружением:
ubuntu-latest незаметно стал Ubuntu 24.04, где пакет libasound2 переименован.Исправление:
# before
- run: playwright install --with-deps chromium
# after
- run: |
sudo apt-get update
sudo apt-get install -y libasound2t64 libnss3 libnspr4
- run: playwright install chromium
В итоге всё заработало. Я получил письмо с подтверждением от Stern Grove и через Resend. Стек технологий:
Вы можете повторить эту автоматизацию для любой еженедельной задачи. Начните с малого: forkните репозиторий, настройте секреты в GitHub Actions и адаптируйте код под свой сайт. Главное — всегда инспектируйте реальную страницу перед написанием автоматизации.
Хочешь закрепить знания на практике?
Решай задачи на Algolit — интерактивная платформа для обучения
Начать бесплатно →