feat(DynamicFetcher): Use persistent context by default for better stealth
And might solve the sandbox issue with GitHub
This commit is contained in:
@@ -56,16 +56,43 @@ def _set_flags(hide_canvas, disable_webgl):
|
|||||||
|
|
||||||
|
|
||||||
@lru_cache(2, typed=True)
|
@lru_cache(2, typed=True)
|
||||||
def _launch_kwargs(headless, real_chrome, stealth, hide_canvas, disable_webgl) -> Tuple:
|
def _launch_kwargs(
|
||||||
|
headless,
|
||||||
|
proxy,
|
||||||
|
locale,
|
||||||
|
extra_headers,
|
||||||
|
useragent,
|
||||||
|
real_chrome,
|
||||||
|
stealth,
|
||||||
|
hide_canvas,
|
||||||
|
disable_webgl,
|
||||||
|
) -> Tuple:
|
||||||
"""Creates the arguments we will use while launching playwright's browser"""
|
"""Creates the arguments we will use while launching playwright's browser"""
|
||||||
launch_kwargs = {
|
launch_kwargs = {
|
||||||
"headless": headless,
|
"headless": headless,
|
||||||
"ignore_default_args": HARMFUL_DEFAULT_ARGS,
|
"ignore_default_args": HARMFUL_DEFAULT_ARGS,
|
||||||
"channel": "chrome" if real_chrome else "chromium",
|
"channel": "chrome" if real_chrome else "chromium",
|
||||||
|
"proxy": proxy or tuple(),
|
||||||
|
"locale": locale,
|
||||||
|
"color_scheme": "dark", # Bypasses the 'prefersLightColor' check in creepjs
|
||||||
|
"device_scale_factor": 2,
|
||||||
|
"extra_http_headers": extra_headers or tuple(),
|
||||||
|
"user_agent": useragent or __default_useragent__,
|
||||||
}
|
}
|
||||||
if stealth:
|
if stealth:
|
||||||
launch_kwargs.update(
|
launch_kwargs.update(
|
||||||
{"args": _set_flags(hide_canvas, disable_webgl), "chromium_sandbox": True}
|
{
|
||||||
|
"args": _set_flags(hide_canvas, disable_webgl),
|
||||||
|
"chromium_sandbox": True,
|
||||||
|
"is_mobile": False,
|
||||||
|
"has_touch": False,
|
||||||
|
# I'm thinking about disabling it to rest from all Service Workers' headache, but let's keep it as it is for now
|
||||||
|
"service_workers": "allow",
|
||||||
|
"ignore_https_errors": True,
|
||||||
|
"screen": {"width": 1920, "height": 1080},
|
||||||
|
"viewport": {"width": 1920, "height": 1080},
|
||||||
|
"permissions": ["geolocation", "notifications"],
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return tuple(launch_kwargs.items())
|
return tuple(launch_kwargs.items())
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ from playwright.sync_api import (
|
|||||||
Response as SyncPlaywrightResponse,
|
Response as SyncPlaywrightResponse,
|
||||||
sync_playwright,
|
sync_playwright,
|
||||||
BrowserType,
|
BrowserType,
|
||||||
Browser,
|
|
||||||
BrowserContext,
|
BrowserContext,
|
||||||
Playwright,
|
Playwright,
|
||||||
Locator,
|
Locator,
|
||||||
@@ -14,7 +13,6 @@ from playwright.async_api import (
|
|||||||
async_playwright,
|
async_playwright,
|
||||||
Response as AsyncPlaywrightResponse,
|
Response as AsyncPlaywrightResponse,
|
||||||
BrowserType as AsyncBrowserType,
|
BrowserType as AsyncBrowserType,
|
||||||
Browser as AsyncBrowser,
|
|
||||||
BrowserContext as AsyncBrowserContext,
|
BrowserContext as AsyncBrowserContext,
|
||||||
Playwright as AsyncPlaywright,
|
Playwright as AsyncPlaywright,
|
||||||
Locator as AsyncLocator,
|
Locator as AsyncLocator,
|
||||||
@@ -177,7 +175,6 @@ class DynamicSession:
|
|||||||
self.wait_selector_state = config.wait_selector_state
|
self.wait_selector_state = config.wait_selector_state
|
||||||
|
|
||||||
self.playwright: Optional[Playwright] = None
|
self.playwright: Optional[Playwright] = None
|
||||||
self.browser: Optional[Union[BrowserType, Browser]] = None
|
|
||||||
self.context: Optional[BrowserContext] = None
|
self.context: Optional[BrowserContext] = None
|
||||||
self.page_pool = PagePool(self.max_pages)
|
self.page_pool = PagePool(self.max_pages)
|
||||||
self._closed = False
|
self._closed = False
|
||||||
@@ -191,15 +188,25 @@ class DynamicSession:
|
|||||||
self.__initiate_browser_options__()
|
self.__initiate_browser_options__()
|
||||||
|
|
||||||
def __initiate_browser_options__(self):
|
def __initiate_browser_options__(self):
|
||||||
|
# `launch_options` is used with persistent context
|
||||||
self.launch_options = dict(
|
self.launch_options = dict(
|
||||||
_launch_kwargs(
|
_launch_kwargs(
|
||||||
self.headless,
|
self.headless,
|
||||||
|
self.proxy,
|
||||||
|
self.locale,
|
||||||
|
tuple(self.extra_headers.items()) if self.extra_headers else tuple(),
|
||||||
|
self.useragent,
|
||||||
self.real_chrome,
|
self.real_chrome,
|
||||||
self.stealth,
|
self.stealth,
|
||||||
self.hide_canvas,
|
self.hide_canvas,
|
||||||
self.disable_webgl,
|
self.disable_webgl,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
self.launch_options["extra_http_headers"] = dict(
|
||||||
|
self.launch_options["extra_http_headers"]
|
||||||
|
)
|
||||||
|
self.launch_options["proxy"] = dict(self.launch_options["proxy"]) or None
|
||||||
|
# while `context_options` is left to be used when cdp mode is enabled
|
||||||
self.context_options = dict(
|
self.context_options = dict(
|
||||||
_context_kwargs(
|
_context_kwargs(
|
||||||
self.proxy,
|
self.proxy,
|
||||||
@@ -223,15 +230,17 @@ class DynamicSession:
|
|||||||
|
|
||||||
self.playwright = sync_context().start()
|
self.playwright = sync_context().start()
|
||||||
|
|
||||||
browser_launcher = getattr(
|
browser_launcher: BrowserType = getattr(
|
||||||
self.playwright, "chrome" if self.real_chrome else "chromium"
|
self.playwright, "chrome" if self.real_chrome else "chromium"
|
||||||
)
|
)
|
||||||
if self.cdp_url:
|
if self.cdp_url:
|
||||||
self.browser = browser_launcher.connect_over_cdp(endpoint_url=self.cdp_url)
|
browser = browser_launcher.connect_over_cdp(endpoint_url=self.cdp_url)
|
||||||
|
self.context = browser.new_context(**self.context_options)
|
||||||
else:
|
else:
|
||||||
self.browser = browser_launcher.launch(**self.launch_options)
|
self.context = browser_launcher.launch_persistent_context(
|
||||||
|
user_data_dir="", **self.launch_options
|
||||||
|
)
|
||||||
|
|
||||||
self.context = self.browser.new_context(**self.context_options)
|
|
||||||
if self.cookies:
|
if self.cookies:
|
||||||
self.context.add_cookies(self.cookies)
|
self.context.add_cookies(self.cookies)
|
||||||
|
|
||||||
@@ -251,10 +260,6 @@ class DynamicSession:
|
|||||||
self.context.close()
|
self.context.close()
|
||||||
self.context = None
|
self.context = None
|
||||||
|
|
||||||
if self.browser:
|
|
||||||
self.browser.close()
|
|
||||||
self.browser = None
|
|
||||||
|
|
||||||
if self.playwright:
|
if self.playwright:
|
||||||
self.playwright.stop()
|
self.playwright.stop()
|
||||||
self.playwright = None
|
self.playwright = None
|
||||||
@@ -459,7 +464,6 @@ class AsyncDynamicSession(DynamicSession):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.playwright: Optional[AsyncPlaywright] = None
|
self.playwright: Optional[AsyncPlaywright] = None
|
||||||
self.browser: Optional[Union[AsyncBrowserType, AsyncBrowser]] = None
|
|
||||||
self.context: Optional[AsyncBrowserContext] = None
|
self.context: Optional[AsyncBrowserContext] = None
|
||||||
self._lock = Lock()
|
self._lock = Lock()
|
||||||
self.__enter__ = None
|
self.__enter__ = None
|
||||||
@@ -478,14 +482,15 @@ class AsyncDynamicSession(DynamicSession):
|
|||||||
self.playwright, "chrome" if self.real_chrome else "chromium"
|
self.playwright, "chrome" if self.real_chrome else "chromium"
|
||||||
)
|
)
|
||||||
if self.cdp_url:
|
if self.cdp_url:
|
||||||
self.browser = await browser_launcher.connect_over_cdp(
|
browser = await browser_launcher.connect_over_cdp(endpoint_url=self.cdp_url)
|
||||||
endpoint_url=self.cdp_url
|
self.context: AsyncBrowserContext = await browser.new_context(
|
||||||
|
**self.context_options
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.browser = await browser_launcher.launch(**self.launch_options)
|
self.context: AsyncBrowserContext = (
|
||||||
|
await browser_launcher.launch_persistent_context(
|
||||||
self.context: AsyncBrowserContext = await self.browser.new_context(
|
user_data_dir="", **self.launch_options
|
||||||
**self.context_options
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.cookies:
|
if self.cookies:
|
||||||
@@ -507,10 +512,6 @@ class AsyncDynamicSession(DynamicSession):
|
|||||||
await self.context.close()
|
await self.context.close()
|
||||||
self.context = None
|
self.context = None
|
||||||
|
|
||||||
if self.browser:
|
|
||||||
await self.browser.close()
|
|
||||||
self.browser = None
|
|
||||||
|
|
||||||
if self.playwright:
|
if self.playwright:
|
||||||
await self.playwright.stop()
|
await self.playwright.stop()
|
||||||
self.playwright = None
|
self.playwright = None
|
||||||
|
|||||||
Reference in New Issue
Block a user