Skip to content

Playwright Mobile

MobilePlaywrightSession

Mobile Playwright session manager for web scrapers.

Source code in src/libeunhaeng/playwright_mobile.py
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
class MobilePlaywrightSession:
    """Mobile Playwright session manager for web scrapers."""

    def __init__(self, headless: bool = False, base_url: str | None = None):
        self.headless = headless
        self.base_url = base_url
        self.browser: Browser | None = None
        self.context: BrowserContext | None = None
        self.page: Page | None = None
        self._playwright = None

    async def __aenter__(self):
        await self.start()
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self.close()

    async def start(self):
        """Initialize a mobile-like Playwright session."""
        if self.browser:
            return

        self._playwright = await async_playwright().start()

        self.browser = await self._playwright.chromium.launch(
            headless=self.headless,
            slow_mo=300,  # Slow down for stability
        )

        self.context = await self.browser.new_context(
            user_agent=MOBILE_USER_AGENT,
            viewport={"width": 375, "height": 812},
            device_scale_factor=3,
            is_mobile=True,
            has_touch=True,
        )

        self.page = await self.context.new_page()
        await self.page.add_init_script(SAFARI_MIMICRY_SCRIPT)

    async def close(self):
        """Close browser and cleanup."""
        if self.browser:
            await self.browser.close()
            self.browser = None
            self.context = None
            self.page = None

        if self._playwright:
            await self._playwright.stop()
            self._playwright = None

close() async

Close browser and cleanup.

Source code in src/libeunhaeng/playwright_mobile.py
76
77
78
79
80
81
82
83
84
85
86
async def close(self):
    """Close browser and cleanup."""
    if self.browser:
        await self.browser.close()
        self.browser = None
        self.context = None
        self.page = None

    if self._playwright:
        await self._playwright.stop()
        self._playwright = None

start() async

Initialize a mobile-like Playwright session.

Source code in src/libeunhaeng/playwright_mobile.py
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
async def start(self):
    """Initialize a mobile-like Playwright session."""
    if self.browser:
        return

    self._playwright = await async_playwright().start()

    self.browser = await self._playwright.chromium.launch(
        headless=self.headless,
        slow_mo=300,  # Slow down for stability
    )

    self.context = await self.browser.new_context(
        user_agent=MOBILE_USER_AGENT,
        viewport={"width": 375, "height": 812},
        device_scale_factor=3,
        is_mobile=True,
        has_touch=True,
    )

    self.page = await self.context.new_page()
    await self.page.add_init_script(SAFARI_MIMICRY_SCRIPT)

PlaywrightSessionManager

Manages Playwright session lifecycle for scrapers using composition. Provides a cleaner interface for scrapers to manage browser sessions.

Source code in src/libeunhaeng/playwright_mobile.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
class PlaywrightSessionManager:
    """
    Manages Playwright session lifecycle for scrapers using composition.
    Provides a cleaner interface for scrapers to manage browser sessions.
    """

    def __init__(self, headless: bool = False, base_url: str | None = None):
        self.headless = headless
        self.base_url = base_url
        self._session_cm = None

    async def __aenter__(self):
        """Start the session and return browser, context, page tuple."""
        self._session_cm = mobile_playwright_session(self.headless, self.base_url)
        return await self._session_cm.__aenter__()

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """Clean up the session."""
        if self._session_cm:
            await self._session_cm.__aexit__(exc_type, exc_val, exc_tb)
            self._session_cm = None

__aenter__() async

Start the session and return browser, context, page tuple.

Source code in src/libeunhaeng/playwright_mobile.py
114
115
116
117
async def __aenter__(self):
    """Start the session and return browser, context, page tuple."""
    self._session_cm = mobile_playwright_session(self.headless, self.base_url)
    return await self._session_cm.__aenter__()

__aexit__(exc_type, exc_val, exc_tb) async

Clean up the session.

Source code in src/libeunhaeng/playwright_mobile.py
119
120
121
122
123
async def __aexit__(self, exc_type, exc_val, exc_tb):
    """Clean up the session."""
    if self._session_cm:
        await self._session_cm.__aexit__(exc_type, exc_val, exc_tb)
        self._session_cm = None

mobile_playwright_session(headless=False, base_url=None) async

Context manager that yields (browser, context, page) with shared mobile settings applied. Uses MobilePlaywrightSession internally without requiring inheritance.

Source code in src/libeunhaeng/playwright_mobile.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
@asynccontextmanager
async def mobile_playwright_session(headless: bool = False, base_url: str | None = None):
    """
    Context manager that yields (browser, context, page) with shared mobile settings applied.
    Uses MobilePlaywrightSession internally without requiring inheritance.
    """
    session = MobilePlaywrightSession(headless=headless, base_url=base_url)
    await session.start()
    try:
        yield session.browser, session.context, session.page
    finally:
        await session.close()