refactor/feat(browser fetchers): make it possible to have a configuration per page in sessions

- Also, no need for the `page_action` argument function to return the page again
This commit is contained in:
Karim shoair
2025-09-11 03:48:55 +03:00
parent 931993f901
commit 9838d741d0
3 changed files with 291 additions and 66 deletions
+26 -11
View File
@@ -22,6 +22,7 @@ from ._config_tools import _compiled_stealth_scripts
from ._validators import validate, PlaywrightConfig, CamoufoxConfig
from ._config_tools import _launch_kwargs, _context_kwargs
from scrapling.core._types import (
Any,
Dict,
Optional,
)
@@ -38,7 +39,12 @@ class SyncSession:
self.context: Optional[BrowserContext] = None
self._closed = False
def _get_page(self) -> PageInfo: # pragma: no cover
def _get_page(
self,
timeout: int | float,
extra_headers: Optional[Dict[str, str]],
disable_resources: bool,
) -> PageInfo: # pragma: no cover
"""Get a new page to use"""
# Close all finished pages to ensure clean state
@@ -59,13 +65,12 @@ class SyncSession:
)
page = self.context.new_page()
timeout = getattr(self, "timeout", 30000)
page.set_default_navigation_timeout(timeout)
page.set_default_timeout(timeout)
if getattr(self, "extra_headers", False):
page.set_extra_http_headers(getattr(self, "extra_headers"))
if extra_headers:
page.set_extra_http_headers(extra_headers)
if getattr(self, "disable_resources", False):
if disable_resources:
page.route("**/*", intercept_route)
if getattr(self, "stealth", False):
@@ -74,6 +79,13 @@ class SyncSession:
return self.page_pool.add_page(page)
@staticmethod
def _get_with_precedence(
request_value: Any, session_value: Any, sentinel_value: object
) -> Any:
"""Get value with request-level priority over session-level"""
return request_value if request_value is not sentinel_value else session_value
def get_pool_stats(self) -> Dict[str, int]:
"""Get statistics about the current page pool"""
return {
@@ -90,7 +102,12 @@ class AsyncSession(SyncSession):
self.context: Optional[AsyncBrowserContext] = None
self._lock = Lock()
async def _get_page(self) -> PageInfo: # pragma: no cover
async def _get_page(
self,
timeout: int | float,
extra_headers: Optional[Dict[str, str]],
disable_resources: bool,
) -> PageInfo: # pragma: no cover
"""Get a new page to use"""
async with self._lock:
# Close all finished pages to ensure clean state
@@ -111,13 +128,12 @@ class AsyncSession(SyncSession):
)
page = await self.context.new_page()
timeout = getattr(self, "timeout", 30000)
page.set_default_navigation_timeout(timeout)
page.set_default_timeout(timeout)
if getattr(self, "extra_headers", False):
await page.set_extra_http_headers(getattr(self, "extra_headers"))
if extra_headers:
await page.set_extra_http_headers(extra_headers)
if getattr(self, "disable_resources", False):
if disable_resources:
await page.route("**/*", async_intercept_route)
if getattr(self, "stealth", False):
@@ -334,7 +350,6 @@ class StealthySessionMixin:
self.geoip = config.geoip
self.selector_config = config.selector_config
self.additional_args = config.additional_args
self.selector_config = config.selector_config
self.page_action = config.page_action
self._headers_keys = (
set(map(str.lower, self.extra_headers.keys()))