Разбираем полный цикл построения надёжного скрейпера для Temu: от выбора стека и прокси до обхода JavaScript‑челленджей и сбора тысяч карточек товаров без единого 403.
Проблематика и требования
-
Антибот‑защита Temu
-
JS‑челленджи и динамические куки;
-
блокировка по повторяющимся заголовкам и шаблонному поведению;
-
гео‑таргетинг: часть контента недоступна вне целевых регионов.
-
-
Цели скрейпинга
-
сбор названий, цен, рейтингов и ссылок на товары;
-
устойчивость к бану при сотнях параллельных сессий;
-
масштабируемость: легко добавить новые категории или регионы.
-
Технологический стек
-
Язык: Python 3.11+
-
Браузер: Playwright (Chromium) в headless‑режиме
-
Асинхронность: asyncio + встроенные возможности Playwright
-
Прокси: ProxyEmpire (ротация IP, порт 5000, аутентификация user:pass)
-
Парсинг: CSS‑селекторы; для сложных фрагментов — lxml/BeautifulSoup
Архитектура решения
[Список URL категорий] ↓ (async dispatcher) [Pool Playwright contexts] ← ProxyEmpire (ротация IP) ↓ [Рендеринг страниц → селекторы → парсинг] ↓ [Сохранение: CSV / PostgreSQL / MongoDB]
-
Playwright contexts изолируют куки и localStorage между задачами.
-
Ротация IP при создании каждого context: новый proxy-сервер.
-
Логирование всех ошибок и задержек для последующего анализа.
Конфигурация ProxyEmpire
# credentials.py PROXY_USER = "ваш_логин" PROXY_PASS = "ваш_пароль" PROXY_HOST = "gateway.proxyempire.io" PROXY_PORT = 5000
-
Пул из 5000 IP (США, ЕС, АЗИЯ и др.).
-
Аутентификация через HTTP Basic.
-
Round‑robin ротация на уровне TCP‑соединений Playwright.
Код: асинхронный скрейпер
# scraper.py import asyncio import logging from playwright.async_api import async_playwright, TimeoutError as PlaywrightTimeout from credentials import PROXY_USER, PROXY_PASS, PROXY_HOST, PROXY_PORT logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") CATEGORY_URLS = [ "https://www.temu.com/ru/computers-and-office-c-123.html", # добавьте другие разделы ] async def fetch_category(page, url): try: await page.goto(url, timeout=60000) await page.wait_for_selector("div[class*='product-card']", timeout=10000) cards = await page.query_selector_all("div[class*='product-card']") results = [] for card in cards: title = await card.query_selector_eval("h3", "el => el.innerText.trim()") price = await card.query_selector_eval("div[class*='price']", "el => el.innerText.trim()") link = await card.query_selector_eval("a", "el => el.href") results.append({"title": title, "price": price, "link": link}) logging.info(f"[{url}] Собрано {len(results)} карточек") return results except PlaywrightTimeout as te: logging.warning(f"[{url}] Таймаут: {te}") except Exception as ex: logging.error(f"[{url}] Ошибка: {ex}") return [] async def worker(name, url_queue, output): proxy_url = f"http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}" async with async_playwright() as p: browser = await p.chromium.launch(headless=True) while not url_queue.empty(): url = await url_queue.get() context = await browser.new_context(proxy={"server": proxy_url}) page = await context.new_page() data = await fetch_category(page, url) output.extend(data) await context.close() await asyncio.sleep(1) # необходимая задержка url_queue.task_done() await browser.close() async def main(): url_queue = asyncio.Queue() for url in CATEGORY_URLS: await url_queue.put(url) results = [] workers = [asyncio.create_task(worker(f"worker-{i}", url_queue, results)) for i in range(5)] # 5 параллельных контекстов await url_queue.join() for w in workers: w.cancel() # Сохранение в CSV import csv with open("temu_products.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["title", "price", "link"]) writer.writeheader() writer.writerows(results) logging.info(f"Итого собрано: {len(results)} записей") if __name__ == "__main__": asyncio.run(main())
Ключевые моменты реализации:
-
Queue + worker‑pattern для динамического распределения URL;
-
Изоляция контекстов Playwright для чистых сессий;
-
ProxyEmpire задаётся при создании context;
-
Обработка ошибок: таймауты и неожиданные исключения логируются и не прерывают работу.
Тонкости обхода защиты
-
Динамические заголовки
-
Добавить ротацию User‑Agent: список популярных браузеров;
-
Маскировать головы:
Accept-Language,Referer.
-
-
Anti-Detect
-
Включить эмуляцию браузерных свойств:
-
context = await browser.new_context( proxy={...}, user_agent=random.choice(USER_AGENTS), viewport={"width": 1280, "height": 720}, java_script_enabled=True )Куки и localStorage Для части страниц требуется авторизация: сохранять и перезагружать state; Captcha‑защита Если появляются invisible reCAPTCHA, можно интегрировать антикапча-сервис.
3.Куки и localStorage
-
Для части страниц требуется авторизация: сохранять и перезагружать state;
4.Captcha‑защита
-
Если появляются invisible reCAPTCHA, можно интегрировать антикапча-сервис.
8. Выводы и рекомендации
-
Headless‑браузер + прокси — оптимальный дуэт при сложных антибот‑механизмах.
-
Изоляция сессий Playwright избавляет от “протекания” куки между задачами.
-
Тонкая настройка User‑Agent, заголовков и задержек снижает подозрительное поведение.
-
ProxyEmpire с портом 5000 обеспечивает качественную ротацию IP и гео‑таргетинг.
Полезные ссылки
-
Playwright Python: https://playwright.dev/python/
-
ProxyEmpire: https://proxyempire.io/
-
Документация Temu (для разработчиков): https://www.temu.com/
ссылка на оригинал статьи https://habr.com/ru/articles/934080/
Добавить комментарий