add cookie session persistence
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import signal
|
||||
import time
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
from playwright.sync_api import Error as PlaywrightError
|
||||
from playwright.sync_api import BrowserContext, Page, sync_playwright
|
||||
@@ -86,6 +90,7 @@ class IAAIScraper:
|
||||
def close(self) -> None:
|
||||
if self.context is not None:
|
||||
try:
|
||||
self._save_storage_state()
|
||||
self.context.close()
|
||||
except PlaywrightError:
|
||||
pass
|
||||
@@ -106,12 +111,51 @@ class IAAIScraper:
|
||||
finally:
|
||||
self.playwright = None
|
||||
|
||||
def _load_storage_state(self) -> str | None:
|
||||
"""Load saved browser session (cookies + localStorage) if valid."""
|
||||
session_cfg = self.settings.session
|
||||
if not session_cfg.enabled:
|
||||
return None
|
||||
state_path = session_cfg.storage_state_path
|
||||
if not state_path or not os.path.isfile(state_path):
|
||||
logger.info("No saved session found at %s", state_path)
|
||||
return None
|
||||
try:
|
||||
mtime = os.path.getmtime(state_path)
|
||||
age_days = (time.time() - mtime) / 86400
|
||||
if age_days > session_cfg.max_age_days:
|
||||
logger.info("Session expired (%.1f days old, max %d). Starting fresh.", age_days, session_cfg.max_age_days)
|
||||
os.remove(state_path)
|
||||
return None
|
||||
logger.info("Reusing saved session from %s (%.1f days old)", state_path, age_days)
|
||||
return state_path
|
||||
except Exception as exc:
|
||||
logger.warning("Failed to load session state: %s", exc)
|
||||
return None
|
||||
|
||||
def _save_storage_state(self) -> None:
|
||||
"""Save browser session (cookies + localStorage) to disk."""
|
||||
session_cfg = self.settings.session
|
||||
if not session_cfg.enabled or not session_cfg.save_on_exit:
|
||||
return
|
||||
if not self.context:
|
||||
return
|
||||
state_path = session_cfg.storage_state_path
|
||||
try:
|
||||
Path(state_path).parent.mkdir(parents=True, exist_ok=True)
|
||||
self.context.storage_state(path=state_path)
|
||||
logger.info("Session state saved to %s", state_path)
|
||||
except Exception as exc:
|
||||
logger.warning("Failed to save session state: %s", exc)
|
||||
|
||||
def _new_context(self, storage_state: str | None = None) -> BrowserContext:
|
||||
if self.browser is None:
|
||||
self.__enter__()
|
||||
if self.context:
|
||||
self._save_storage_state()
|
||||
self.context.close()
|
||||
self.context = self.browser_factory.create_context(self.browser, storage_state=storage_state)
|
||||
effective_state = storage_state or self._load_storage_state()
|
||||
self.context = self.browser_factory.create_context(self.browser, storage_state=effective_state)
|
||||
return self.context
|
||||
|
||||
def init_db(self):
|
||||
|
||||
Reference in New Issue
Block a user