Перейти к содержанию
  • Лента
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы
Свернуть
exlends
Категории
  1. Главная
  2. Категории
  3. Языки программирования
  4. TypeScript
  5. Автоматизация парсинга динамических сайтов: Playwright + Bun + Zod в TypeScript

Автоматизация парсинга динамических сайтов: Playwright + Bun + Zod в TypeScript

Запланировано Прикреплена Закрыта Перенесена TypeScript
playwrightbunzod
1 Сообщения 1 Постеры 3 Просмотры
  • Сначала старые
  • Сначала новые
  • По количеству голосов
Ответить
  • Ответить, создав новую тему
Авторизуйтесь, чтобы ответить
Эта тема была удалена. Только пользователи с правом управления темами могут её видеть.
  • kirilljsxK Не в сети
    kirilljsxK Не в сети
    kirilljsx
    js
    написал отредактировано
    #1

    Обложка: Как автоматизировать парсинг динамических сайтов с Playwright, Bun и Zod в TypeScript: DIY-скрипт для full-stack автоматизации

    Динамические сайты с кучей JavaScript - это головная боль для парсеров. Обычный fetch или axios не вытащат контент, который грузится асинхронно. Здесь на помощь приходит Playwright - он запускает реальный браузер и эмулирует действия юзера.

    Соберем full-stack скрипт на Bun для скорости, TypeScript для типизации и Zod для валидации данных. Это сэкономит часы на ручном сборе данных, идеально для бизнеса: цены конкурентов, отзывы или новости. Получится быстрый парсер, который легко деплоить и масштабировать.

    Почему Playwright рвет шаблон для динамики

    Современные сайты вроде Instagram или Twitch пихают весь сок в JS: ленты скроллятся бесконечно, фильтры подгружаются AJAX-ом. Простой HTTP-запрос вернет голый HTML без нужного. Playwright решает это headless-браузером - Chromium, Firefox или Webkit на выбор.

    Он не просто грузит страницу, а ждёт, пока JS отработает, кликает кнопки, скроллит и даже меняет user-agent. Представь: парсим каталог товаров с пагинацией - клик, ввод в поиск, скролл до конца. Без багов с теневым DOM или iframe-ами. А с TypeScript код становится предсказуемым, без сюрпризов в runtime.

    • Headless-режим: браузер не виден, жрёт меньше ресурсов, идеально для сервака.
    • Эмуляция действий: page.click(), page.fill() - как настоящий юзер, обходит антиботы.
    • Скриншоты и видео: page.screenshot() для дебага, если что-то сломалось.
    Фича Playwright Puppeteer Selenium
    Браузеры Chromium, Firefox, Webkit Только Chromium Все, но медленнее
    Скорость Высокая, async Хорошая Средняя
    TypeScript Нативная поддержка Через @types Сложнее

    Нюанс: всегда ставь таймауты - waitForSelector() с timeout: 10000, чтоб не висеть вечно.

    Bun - турбо-ускоритель для Node-скриптов

    Bun - это не просто runtime, а замена Node.js с JavaScriptCore. Установка пакетов в 10x быстрее, запуск скрипта - молния. Для парсера на сервере это критично: парсим 1000 страниц - и не ждём минуты.

    В связке с Playwright Bun тянет всё: bun install playwright, и готово. Нет package-lock.json-войн - bun.lock решает конфликты. Плюс встроенный bundler и test runner. Наткнулся на релиз Bun 1.2 - S3-пакеты в 5 раз шустрее, SQL для Postgres. Идеально для пет-проекта, который вырастет в сервис.

    • Установка: bun init, bun add playwright zod, bun add -d @types/node - секунды.
    • Запуск: bun run parse.ts - без ts-node, нативно.
    • Hot reload: меняешь код - перезапуск мгновенный.
    Сравнение runtime Bun Node.js Deno
    Установка deps 10x быстрее Стандарт Хорош, но меньше экосистемы
    Память Меньше Больше Сопоставимо
    TypeScript Нативно Через tsx Нативно

    Лайфхак: используй Bun.file() для чтения JSON-ов локально, быстрее fs.readFile.

    Zod - типы и валидация в одном флаконе

    Парсинг без схем - лотерея: цена пришла строкой, id - числом. Zod рисует схемы, валидирует и выводит TypeScript-типы автоматически. z.object({ name: z.string(), price: z.number() }) - и тип готов: z.infer<typeof schema>.

    В нашем скрипте Zod проверит данные с Playwright: цена - число, название - строка до 100 символов. Ошибка? parse() кинет ZodError с деталями. Никаких any в типах, автокомплит в VS Code летает. Плюс regex для UUID или имейлов.

    import { z } from 'zod';
    
    const ProductSchema = z.object({
      name: z.string().max(100),
      price: z.string().regex(/\d+/).transform(Number),
      id: z.string().uuid(),
    });
    
    type Product = z.infer<typeof ProductSchema>;
    
    • Преобразования: .transform() - строка в число, дата в Date.
    • Опционалки: z.number().optional() - если цена отсутствует.
    • Массивы: z.array(ProductSchema) для списка товаров.

    Важно: всегда .safeParse() в проде, чтоб не крашить скрипт на кривых данных.

    Полный DIY-скрипт: от запуска до сохранения

    Собираем всё вместе. Скрипт парсит каталог товаров: открывает страницу, применяет фильтры, скроллит, экстрактит данные Zod’ом. Full-stack - frontend эмуляция + backend-логика в одном файле. Запускай на VPS через pm2 или systemd.

    Код готов к копипасту. Настраивай селекторы под свой сайт - используй Playwright Inspector (npx playwright codegen). Сохраняем в JSON или SQLite через Bun.sql.

    import { chromium } from 'playwright';
    import { z } from 'zod';
    
    const Product = z.object({
      name: z.string(),
      price: z.number(),
    });
    
    type Product = z.infer<typeof Product>;
    
    async function parseSite(url: string) {
      const browser = await chromium.launch({ headless: true });
      const page = await browser.newPage();
      await page.goto(url);
    
      // Ждём загрузки
      await page.waitForSelector('[data-product]');
    
      // Скролл для динамики
      await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
    
      const data = await page.evaluate(() => {
        return Array.from(document.querySelectorAll('[data-product]')).map(el => ({
          name: el.querySelector('.name')?.textContent || '',
          price: parseFloat(el.querySelector('.price')?.textContent || '0'),
        }));
      });
    
      const products = z.array(Product).parse(data);
      await browser.close();
      return products;
    }
    
    // Запуск
    const products = await parseSite('https://example.com/shop');
    console.log(products);
    Bun.write(Bun.file('products.json'), JSON.stringify(products));
    
    • Расширение: добавь прокси page.route() для ротации IP.
    • Параллель: Promise.all() для нескольких страниц.
    • Логи: test.step() из Playwright для отладки.
    Шаг Команда
    Установка bun add playwright zod
    Запуск bun run parse.ts
    Деплой bun pm2 start parse.ts

    Масштаб за кадром: от скрипта к сервису

    Этот стек тянет от пет-проекта до production: добавь API на Elysia (Bun-фреймворк), кэш в Redis, оркестрацию через Docker. Осталось интегрировать ИИ - отправь данные в Grok API для анализа цен. Или cron для ежедневного парсинга.

    Динамика эволюционирует - жди фич вроде встроенного AI в Playwright. Подумай о stealth-плагинах против Cloudflare. Код живой, апгрейдь под новые релизы Bun и TypeScript.

    1 ответ Последний ответ
    0

    Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.

    Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.

    С вашими комментариями этот пост мог бы стать ещё лучше 💗

    Зарегистрироваться Войти

    Категории

    • Главная
    • Новости
    • Фронтенд
    • Бекенд
    • Языки программирования

    Контакты

    • Сотрудничество
    • info@exlends.com

    © 2024 - 2026 ExLends, Inc. Все права защищены.

    Политика конфиденциальности
    • Войти

    • Нет учётной записи? Зарегистрироваться

    • Войдите или зарегистрируйтесь для поиска.
    • Первое сообщение
      Последнее сообщение
    0
    • Лента
    • Категории
    • Последние
    • Метки
    • Популярные
    • Пользователи
    • Группы