Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import asyncio
- from collections import deque
- from datetime import datetime
- import time
- from playwright.async_api import Page
- class NetworkIdleWaiter:
- """
- Класс для продвинутого ожидания.
- Запускает таймер и сбрасывает его после каждого загруженного файла.
- Спустя заданное время после последней активности разблокирует поток.
- """
- def __init__(
- self,
- page: Page,
- idle_time: float = 1.0,
- timeout: float = 10.0,
- ignore_resources: list = None,
- print_on: bool = False,
- ):
- self.page = page
- self.idle_time = idle_time
- self.timeout = timeout
- self.ignore_resources = ignore_resources or ['font', 'websocket']
- self.pending_requests = {}
- self.last_activity = time.time()
- self.network_log = deque(maxlen=100) # Последние 100 запросов для отладки
- self.print_on = print_on
- async def wait(self):
- """Ждет пока сеть станет неактивной"""
- # Подписываемся на события
- self.page.on("request", self._on_request)
- self.page.on("response", self._on_response)
- self.page.on("requestfailed", self._on_request_failed)
- start_time = time.time()
- try:
- while True:
- await asyncio.sleep(0.1)
- current_time = time.time()
- idle_duration = current_time - self.last_activity
- # Проверяем условия выхода
- if len(self.pending_requests) == 0 and idle_duration >= self.idle_time:
- if self.print_on:
- print(f"✅ Сеть неактивна {idle_duration:.1f} сек. "
- f"Загрузка завершена!")
- break
- # Проверка таймаута
- if current_time - start_time > self.timeout:
- if self.print_on:
- print(f"⚠️ Таймаут {self.timeout} сек. "
- f"Остались запросы: {len(self.pending_requests)}")
- if self.pending_requests:
- print("Незавершенные запросы:")
- for url, info in list(self.pending_requests.items())[:5]:
- print(f" - {info['type']}: {url[:100]}...")
- break
- # Отладочная информация
- if self.print_on:
- if len(self.pending_requests) > 0:
- print(f"⏳ Ожидание... Активных запросов: {len(self.pending_requests)}, "
- f"Idle: {idle_duration:.1f}s")
- finally:
- # Отписываемся от событий
- self.page.remove_listener("request", self._on_request)
- self.page.remove_listener("response", self._on_response)
- self.page.remove_listener("requestfailed", self._on_request_failed)
- def get_stats(self):
- """Получить статистику по сетевой активности"""
- return {
- 'total_requests': len(self.network_log),
- 'pending': len(self.pending_requests),
- 'last_activity': self.last_activity,
- 'log': list(self.network_log)
- }
- # Обработчики событий
- def _on_request(self, request):
- # Игнорируем определенные типы ресурсов
- if request.resource_type in self.ignore_resources:
- return
- self.pending_requests[request.url] = {
- 'start': time.time(),
- 'type': request.resource_type,
- 'method': request.method
- }
- self.last_activity = time.time()
- self.network_log.append({
- 'event': 'request',
- 'url': request.url,
- 'type': request.resource_type,
- 'time': datetime.now().isoformat()
- })
- def _on_response(self, response):
- if response.url in self.pending_requests:
- request_info = self.pending_requests.pop(response.url)
- duration = time.time() - request_info['start']
- self.network_log.append({
- 'event': 'response',
- 'url': response.url,
- 'status': response.status,
- 'duration': duration,
- 'time': datetime.now().isoformat()
- })
- self.last_activity = time.time()
- def _on_request_failed(self, request):
- if request.url in self.pending_requests:
- self.pending_requests.pop(request.url)
- self.network_log.append({
- 'event': 'failed',
- 'url': request.url,
- 'failure': request.failure,
- 'time': datetime.now().isoformat()
- })
- self.last_activity = time.time()
Advertisement
Add Comment
Please, Sign In to add comment