跳转至

Fetcher 类

这里列出了所有 Fetcher 类的参数、属性和方法。

可以直接导入:

from scrapling.fetchers import (
    Fetcher, AsyncFetcher, StealthyFetcher,
    FetcherSession, AsyncStealthySession, StealthySession,
    RemoteSession, AsyncRemoteSession
)

scrapling.fetchers.Fetcher

Fetcher(*args, **kwargs)

基类: BaseFetcher


              flowchart TD
              scrapling.fetchers.Fetcher[Fetcher]
              scrapling.engines.toolbelt.custom.BaseFetcher[BaseFetcher]

                              scrapling.engines.toolbelt.custom.BaseFetcher --> scrapling.fetchers.Fetcher
                


              click scrapling.fetchers.Fetcher href "" "scrapling.fetchers.Fetcher"
              click scrapling.engines.toolbelt.custom.BaseFetcher href "" "scrapling.engines.toolbelt.custom.BaseFetcher"
            

基础 Fetcher 类,通过 curl_cffi 发送 GET、POST、PUT 和 DELETE HTTP 请求。

源代码位于 scrapling/engines/toolbelt/custom.py
def __init__(self, *args, **kwargs):
    # For backward-compatibility before 0.2.99
    args_str = ", ".join(args) or ""
    kwargs_str = ", ".join(f"{k}={v}" for k, v in kwargs.items()) or ""
    if args_str:
        args_str += ", "

    log.warning(
        f"This logic is deprecated now, and have no effect; It will be removed with v0.3. Use `{self.__class__.__name__}.configure({args_str}{kwargs_str})` instead before fetching"
    )
    pass

__slots__ class-attribute instance-attribute

__slots__ = ()

huge_tree class-attribute instance-attribute

huge_tree = True

adaptive class-attribute instance-attribute

adaptive = False

storage class-attribute instance-attribute

storage = SQLiteStorageSystem

storage_args class-attribute instance-attribute

storage_args = None

keep_comments class-attribute instance-attribute

keep_comments = False

adaptive_domain class-attribute instance-attribute

adaptive_domain = ''

parser_keywords class-attribute instance-attribute

parser_keywords = (
    "huge_tree",
    "adaptive",
    "storage",
    "storage_args",
    "keep_comments",
    "adaptive_domain",
)

display_config classmethod

display_config()
源代码位于 scrapling/engines/toolbelt/custom.py
@classmethod
def display_config(cls):
    return dict(
        huge_tree=cls.huge_tree,
        keep_comments=cls.keep_comments,
        adaptive=cls.adaptive,
        storage=cls.storage,
        storage_args=cls.storage_args,
        adaptive_domain=cls.adaptive_domain,
    )

configure classmethod

configure(**kwargs)

一次设置多个全局解析参数。

参数 说明
kwargs

支持的参数有 huge_tree、keep_comments、adaptive、storage、storage_args 和 adaptive_domain。

默认值: {}

源代码位于 scrapling/engines/toolbelt/custom.py
@classmethod
def configure(cls, **kwargs):
    """Set multiple arguments for the parser at once globally

    :param kwargs: The keywords can be any arguments of the following: huge_tree, keep_comments, adaptive, storage, storage_args, adaptive_domain
    """
    for key, value in kwargs.items():
        key = key.strip().lower()
        if hasattr(cls, key):
            if key in cls.parser_keywords:
                setattr(cls, key, value)
            else:
                # Yup, no fun allowed LOL
                raise AttributeError(f'Unknown parser argument: "{key}"; maybe you meant {cls.parser_keywords}?')
        else:
            raise ValueError(f'Unknown parser argument: "{key}"; maybe you meant {cls.parser_keywords}?')

    if not kwargs:
        raise AttributeError(f"You must pass a keyword to configure, current keywords: {cls.parser_keywords}?")

get classmethod

get(url, **kwargs)
源代码位于 scrapling/fetchers/requests.py
@classmethod
def get(cls, url: str, **kwargs: Unpack[GetRequestParams]) -> Response:
    return __FetcherClientInstance__.get(url, **_merge_selector_config(cls, kwargs))

post classmethod

post(url, **kwargs)
源代码位于 scrapling/fetchers/requests.py
@classmethod
def post(cls, url: str, **kwargs: Unpack[DataRequestParams]) -> Response:
    return __FetcherClientInstance__.post(url, **_merge_selector_config(cls, kwargs))

put classmethod

put(url, **kwargs)
源代码位于 scrapling/fetchers/requests.py
@classmethod
def put(cls, url: str, **kwargs: Unpack[DataRequestParams]) -> Response:
    return __FetcherClientInstance__.put(url, **_merge_selector_config(cls, kwargs))

delete classmethod

delete(url, **kwargs)
源代码位于 scrapling/fetchers/requests.py
@classmethod
def delete(cls, url: str, **kwargs: Unpack[DataRequestParams]) -> Response:
    return __FetcherClientInstance__.delete(url, **_merge_selector_config(cls, kwargs))

scrapling.fetchers.AsyncFetcher

AsyncFetcher(*args, **kwargs)

基类: BaseFetcher


              flowchart TD
              scrapling.fetchers.AsyncFetcher[AsyncFetcher]
              scrapling.engines.toolbelt.custom.BaseFetcher[BaseFetcher]

                              scrapling.engines.toolbelt.custom.BaseFetcher --> scrapling.fetchers.AsyncFetcher
                


              click scrapling.fetchers.AsyncFetcher href "" "scrapling.fetchers.AsyncFetcher"
              click scrapling.engines.toolbelt.custom.BaseFetcher href "" "scrapling.engines.toolbelt.custom.BaseFetcher"
            

基础 Fetcher 类,通过 curl_cffi 发送 GET、POST、PUT 和 DELETE HTTP 请求。

源代码位于 scrapling/engines/toolbelt/custom.py
def __init__(self, *args, **kwargs):
    # For backward-compatibility before 0.2.99
    args_str = ", ".join(args) or ""
    kwargs_str = ", ".join(f"{k}={v}" for k, v in kwargs.items()) or ""
    if args_str:
        args_str += ", "

    log.warning(
        f"This logic is deprecated now, and have no effect; It will be removed with v0.3. Use `{self.__class__.__name__}.configure({args_str}{kwargs_str})` instead before fetching"
    )
    pass

__slots__ class-attribute instance-attribute

__slots__ = ()

huge_tree class-attribute instance-attribute

huge_tree = True

adaptive class-attribute instance-attribute

adaptive = False

storage class-attribute instance-attribute

storage = SQLiteStorageSystem

storage_args class-attribute instance-attribute

storage_args = None

keep_comments class-attribute instance-attribute

keep_comments = False

adaptive_domain class-attribute instance-attribute

adaptive_domain = ''

parser_keywords class-attribute instance-attribute

parser_keywords = (
    "huge_tree",
    "adaptive",
    "storage",
    "storage_args",
    "keep_comments",
    "adaptive_domain",
)

display_config classmethod

display_config()
源代码位于 scrapling/engines/toolbelt/custom.py
@classmethod
def display_config(cls):
    return dict(
        huge_tree=cls.huge_tree,
        keep_comments=cls.keep_comments,
        adaptive=cls.adaptive,
        storage=cls.storage,
        storage_args=cls.storage_args,
        adaptive_domain=cls.adaptive_domain,
    )

configure classmethod

configure(**kwargs)

一次设置多个全局解析参数。

参数 说明
kwargs

支持的参数有 huge_tree、keep_comments、adaptive、storage、storage_args 和 adaptive_domain。

默认值: {}

源代码位于 scrapling/engines/toolbelt/custom.py
@classmethod
def configure(cls, **kwargs):
    """Set multiple arguments for the parser at once globally

    :param kwargs: The keywords can be any arguments of the following: huge_tree, keep_comments, adaptive, storage, storage_args, adaptive_domain
    """
    for key, value in kwargs.items():
        key = key.strip().lower()
        if hasattr(cls, key):
            if key in cls.parser_keywords:
                setattr(cls, key, value)
            else:
                # Yup, no fun allowed LOL
                raise AttributeError(f'Unknown parser argument: "{key}"; maybe you meant {cls.parser_keywords}?')
        else:
            raise ValueError(f'Unknown parser argument: "{key}"; maybe you meant {cls.parser_keywords}?')

    if not kwargs:
        raise AttributeError(f"You must pass a keyword to configure, current keywords: {cls.parser_keywords}?")

get classmethod

get(url, **kwargs)
源代码位于 scrapling/fetchers/requests.py
@classmethod
def get(cls, url: str, **kwargs: Unpack[GetRequestParams]) -> Awaitable[Response]:
    return __AsyncFetcherClientInstance__.get(url, **_merge_selector_config(cls, kwargs))

post classmethod

post(url, **kwargs)
源代码位于 scrapling/fetchers/requests.py
@classmethod
def post(cls, url: str, **kwargs: Unpack[DataRequestParams]) -> Awaitable[Response]:
    return __AsyncFetcherClientInstance__.post(url, **_merge_selector_config(cls, kwargs))

put classmethod

put(url, **kwargs)
源代码位于 scrapling/fetchers/requests.py
@classmethod
def put(cls, url: str, **kwargs: Unpack[DataRequestParams]) -> Awaitable[Response]:
    return __AsyncFetcherClientInstance__.put(url, **_merge_selector_config(cls, kwargs))

delete classmethod

delete(url, **kwargs)
源代码位于 scrapling/fetchers/requests.py
@classmethod
def delete(cls, url: str, **kwargs: Unpack[DataRequestParams]) -> Awaitable[Response]:
    return __AsyncFetcherClientInstance__.delete(url, **_merge_selector_config(cls, kwargs))

scrapling.fetchers.StealthyFetcher

StealthyFetcher(*args, **kwargs)

基类: BaseFetcher


              flowchart TD
              scrapling.fetchers.StealthyFetcher[StealthyFetcher]
              scrapling.engines.toolbelt.custom.BaseFetcher[BaseFetcher]

                              scrapling.engines.toolbelt.custom.BaseFetcher --> scrapling.fetchers.StealthyFetcher
                


              click scrapling.fetchers.StealthyFetcher href "" "scrapling.fetchers.StealthyFetcher"
              click scrapling.engines.toolbelt.custom.BaseFetcher href "" "scrapling.engines.toolbelt.custom.BaseFetcher"
            

基于 Chromium、提供完整隐身功能的 Fetcher 类。

像真实浏览器一样运行,通过几乎所有在线测试和防护,并提供多种自定义选项。

源代码位于 scrapling/engines/toolbelt/custom.py
def __init__(self, *args, **kwargs):
    # For backward-compatibility before 0.2.99
    args_str = ", ".join(args) or ""
    kwargs_str = ", ".join(f"{k}={v}" for k, v in kwargs.items()) or ""
    if args_str:
        args_str += ", "

    log.warning(
        f"This logic is deprecated now, and have no effect; It will be removed with v0.3. Use `{self.__class__.__name__}.configure({args_str}{kwargs_str})` instead before fetching"
    )
    pass

__slots__ class-attribute instance-attribute

__slots__ = ()

huge_tree class-attribute instance-attribute

huge_tree = True

adaptive class-attribute instance-attribute

adaptive = False

storage class-attribute instance-attribute

storage = SQLiteStorageSystem

storage_args class-attribute instance-attribute

storage_args = None

keep_comments class-attribute instance-attribute

keep_comments = False

adaptive_domain class-attribute instance-attribute

adaptive_domain = ''

parser_keywords class-attribute instance-attribute

parser_keywords = (
    "huge_tree",
    "adaptive",
    "storage",
    "storage_args",
    "keep_comments",
    "adaptive_domain",
)

display_config classmethod

display_config()
源代码位于 scrapling/engines/toolbelt/custom.py
@classmethod
def display_config(cls):
    return dict(
        huge_tree=cls.huge_tree,
        keep_comments=cls.keep_comments,
        adaptive=cls.adaptive,
        storage=cls.storage,
        storage_args=cls.storage_args,
        adaptive_domain=cls.adaptive_domain,
    )

configure classmethod

configure(**kwargs)

一次设置多个全局解析参数。

参数 说明
kwargs

支持的参数有 huge_tree、keep_comments、adaptive、storage、storage_args 和 adaptive_domain。

默认值: {}

源代码位于 scrapling/engines/toolbelt/custom.py
@classmethod
def configure(cls, **kwargs):
    """Set multiple arguments for the parser at once globally

    :param kwargs: The keywords can be any arguments of the following: huge_tree, keep_comments, adaptive, storage, storage_args, adaptive_domain
    """
    for key, value in kwargs.items():
        key = key.strip().lower()
        if hasattr(cls, key):
            if key in cls.parser_keywords:
                setattr(cls, key, value)
            else:
                # Yup, no fun allowed LOL
                raise AttributeError(f'Unknown parser argument: "{key}"; maybe you meant {cls.parser_keywords}?')
        else:
            raise ValueError(f'Unknown parser argument: "{key}"; maybe you meant {cls.parser_keywords}?')

    if not kwargs:
        raise AttributeError(f"You must pass a keyword to configure, current keywords: {cls.parser_keywords}?")

fetch classmethod

fetch(url, **kwargs)

打开浏览器,按下面选择的选项发送请求。

参数 说明
url

目标 URL。

类型: str

headless

以无头模式运行,不显示窗口,这是默认设置;也可以显示浏览器窗口。

disable_resources

阻止不必要的资源请求以提高速度。类型包括 font、image、media、beacon、object、imageset、texttrack、websocket、csp_report 和 stylesheet。

blocked_domains

要阻止请求的域名集合,也会匹配子域名。例如,"example.com" 也会阻止 "sub.example.com"。

block_ads

阻止向约 3,500 个已知广告或跟踪域名发送请求,可与 blocked_domains 结合使用。

dns_over_https

通过 Cloudflare 的 DNS-over-HTTPS 发送 DNS 查询,避免使用代理时发生 DNS 泄露。

useragent

指定 User-Agent 字符串。未指定时,Fetcher 会生成并使用相同浏览器的真实 User-Agent。

cookies

为下一次请求设置 Cookie。

network_idle

等待页面至少连续 500 ms 没有网络连接。

timeout

页面所有操作和等待的超时时间,单位为毫秒,默认为 30,000。

wait

所有步骤完成后,在关闭页面并返回 Response 对象前额外等待的时间,单位为毫秒。

page_action

用于自动化的函数,接收 page 对象,在导航后执行所需操作。

page_setup

接收 page 对象并在导航前执行的函数。用于注册必须在页面加载前准备好的事件监听器或路由。

wait_selector

等待指定 CSS 选择器达到指定状态。

init_script

JavaScript 文件的绝对路径,在此会话中的每个页面创建时执行。

locale

区域设置,例如 en-GB、de-DE。影响 navigator.language、请求头 Accept-Language,以及数字和日期格式。默认使用系统区域设置。

timezone_id

修改浏览器时区,默认使用系统时区。

wait_selector_state

等待 wait_selector 指定的元素达到这个状态。默认为 attached。

solve_cloudflare

返回响应前,处理所有类型的 Cloudflare Turnstile 和 Interstitial 挑战。

real_chrome

如果设备上已安装 Chrome,启用此选项后,Fetcher 会启动并使用它。

hide_canvas

为 Canvas 操作添加随机噪声,防止指纹识别。

block_webrtc

强制 WebRTC 遵守代理设置,避免泄露本地 IP 地址。

allow_webgl

默认开启。关闭后会完全禁用 WebGL 和 WebGL 2.0。不建议关闭,因为很多 WAF 会检查 WebGL 是否启用。

load_dom

等待页面上的所有 JavaScript 加载并执行,默认开启。

pierce_shadow

将开放的 Shadow DOM 内容加入响应 HTML,默认为 False。

google_search

默认开启,Scrapling 会设置 Google referer 请求头。

extra_headers

要添加到请求中的额外请求头字典。同时使用时,google_search 设置的 referer 优先于这里的值。

proxy

请求使用的代理,可以是字符串,或仅包含 'server'、'username'、'password' 的字典。

user_data_dir

用户数据目录的路径,用于保存 Cookie、本地存储等浏览器会话数据。默认创建临时目录。

extra_flags

启动浏览器时传入的额外参数列表。

selector_config

创建最终 Selector 对象时传入的参数。

additional_args

传给 Playwright 上下文的额外设置,优先级高于 Scrapling 设置。

返回 说明
Response

一个 Response 对象。

源代码位于 scrapling/fetchers/stealth_chrome.py
@classmethod
def fetch(cls, url: str, **kwargs: Unpack[StealthSession]) -> Response:
    """
    Opens up a browser and do your request based on your chosen options below.

    :param url: Target url.
    :param headless: Run the browser in headless/hidden (default), or headful/visible mode.
    :param disable_resources: Drop requests for unnecessary resources for a speed boost.
        Requests dropped are of type `font`, `image`, `media`, `beacon`, `object`, `imageset`, `texttrack`, `websocket`, `csp_report`, and `stylesheet`.
    :param blocked_domains: A set of domain names to block requests to. Subdomains are also matched (e.g., ``"example.com"`` blocks ``"sub.example.com"`` too).
    :param block_ads: Block requests to ~3,500 known ad/tracking domains. Can be combined with ``blocked_domains``.
    :param dns_over_https: Route DNS queries through Cloudflare's DNS-over-HTTPS to prevent DNS leaks when using proxies.
    :param useragent: Pass a useragent string to be used. Otherwise the fetcher will generate a real Useragent of the same browser and use it.
    :param cookies: Set cookies for the next request.
    :param network_idle: Wait for the page until there are no network connections for at least 500 ms.
    :param timeout: The timeout in milliseconds that is used in all operations and waits through the page. The default is 30,000
    :param wait: The time (milliseconds) the fetcher will wait after everything finishes before closing the page and returning the ` Response ` object.
    :param page_action: Added for automation. A function that takes the `page` object, runs after navigation, and does the automation you need.
    :param page_setup: A function that takes the `page` object, runs before navigation. Use it to register event listeners or routes that must be set up before the page loads.
    :param wait_selector: Wait for a specific CSS selector to be in a specific state.
    :param init_script: An absolute path to a JavaScript file to be executed on page creation for all pages in this session.
    :param locale: Specify user locale, for example, `en-GB`, `de-DE`, etc. Locale will affect navigator.language value, Accept-Language request header value as well as number and date formatting
        rules. Defaults to the system default locale.
    :param timezone_id: Changes the timezone of the browser. Defaults to the system timezone.
    :param wait_selector_state: The state to wait for the selector given with `wait_selector`. The default state is `attached`.
    :param solve_cloudflare: Solves all types of the Cloudflare's Turnstile/Interstitial challenges before returning the response to you.
    :param real_chrome: If you have a Chrome browser installed on your device, enable this, and the Fetcher will launch an instance of your browser and use it.
    :param hide_canvas: Add random noise to canvas operations to prevent fingerprinting.
    :param block_webrtc: Forces WebRTC to respect proxy settings to prevent local IP address leak.
    :param allow_webgl: Enabled by default. Disabling it disables WebGL and WebGL 2.0 support entirely. Disabling WebGL is not recommended as many WAFs now check if WebGL is enabled.
    :param load_dom: Enabled by default, wait for all JavaScript on page(s) to fully load and execute.
    :param pierce_shadow: Include open Shadow DOM content in the response HTML. Defaults to False.
    :param google_search: Enabled by default, Scrapling will set a Google referer header.
    :param extra_headers: A dictionary of extra headers to add to the request. _The referer set by `google_search` takes priority over the referer set here if used together._
    :param proxy: The proxy to be used with requests, it can be a string or a dictionary with the keys 'server', 'username', and 'password' only.
    :param user_data_dir: Path to a User Data Directory, which stores browser session data like cookies and local storage. The default is to create a temporary directory.
    :param extra_flags: A list of additional browser flags to pass to the browser on launch.
    :param selector_config: The arguments that will be passed in the end while creating the final Selector's class.
    :param additional_args: Additional arguments to be passed to Playwright's context as additional settings, and it takes higher priority than Scrapling's settings.
    :return: A `Response` object.
    """
    selector_config = kwargs.get("selector_config", {}) or kwargs.get(
        "custom_config", {}
    )  # Checking `custom_config` for backward compatibility
    if not isinstance(selector_config, dict):
        raise TypeError("Argument `selector_config` must be a dictionary.")

    kwargs["selector_config"] = {**cls._generate_parser_arguments(), **selector_config}

    with StealthySession(**kwargs) as engine:
        return engine.fetch(url)

async_fetch async classmethod

async_fetch(url, **kwargs)

打开浏览器,按下面选择的选项发送请求。

参数 说明
url

目标 URL。

类型: str

headless

以无头模式运行,不显示窗口,这是默认设置;也可以显示浏览器窗口。

disable_resources

阻止不必要的资源请求以提高速度。类型包括 font、image、media、beacon、object、imageset、texttrack、websocket、csp_report 和 stylesheet。

blocked_domains

要阻止请求的域名集合,也会匹配子域名。例如,"example.com" 也会阻止 "sub.example.com"。

block_ads

阻止向约 3,500 个已知广告或跟踪域名发送请求,可与 blocked_domains 结合使用。

dns_over_https

通过 Cloudflare 的 DNS-over-HTTPS 发送 DNS 查询,避免使用代理时发生 DNS 泄露。

useragent

指定 User-Agent 字符串。未指定时,Fetcher 会生成并使用相同浏览器的真实 User-Agent。

cookies

为下一次请求设置 Cookie。

network_idle

等待页面至少连续 500 ms 没有网络连接。

timeout

页面所有操作和等待的超时时间,单位为毫秒,默认为 30,000。

wait

所有步骤完成后,在关闭页面并返回 Response 对象前额外等待的时间,单位为毫秒。

page_action

用于自动化的函数,接收 page 对象,在导航后执行所需操作。

page_setup

接收 page 对象并在导航前执行的函数。用于注册必须在页面加载前准备好的事件监听器或路由。

wait_selector

等待指定 CSS 选择器达到指定状态。

init_script

JavaScript 文件的绝对路径,在此会话中的每个页面创建时执行。

locale

区域设置,例如 en-GB、de-DE。影响 navigator.language、请求头 Accept-Language,以及数字和日期格式。默认使用系统区域设置。

timezone_id

修改浏览器时区,默认使用系统时区。

wait_selector_state

等待 wait_selector 指定的元素达到这个状态。默认为 attached。

solve_cloudflare

返回响应前,处理所有类型的 Cloudflare Turnstile 和 Interstitial 挑战。

real_chrome

如果设备上已安装 Chrome,启用此选项后,Fetcher 会启动并使用它。

hide_canvas

为 Canvas 操作添加随机噪声,防止指纹识别。

block_webrtc

强制 WebRTC 遵守代理设置,避免泄露本地 IP 地址。

allow_webgl

默认开启。关闭后会完全禁用 WebGL 和 WebGL 2.0。不建议关闭,因为很多 WAF 会检查 WebGL 是否启用。

load_dom

等待页面上的所有 JavaScript 加载并执行,默认开启。

pierce_shadow

将开放的 Shadow DOM 内容加入响应 HTML,默认为 False。

google_search

默认开启,Scrapling 会设置 Google referer 请求头。

extra_headers

要添加到请求中的额外请求头字典。同时使用时,google_search 设置的 referer 优先于这里的值。

proxy

请求使用的代理,可以是字符串,或仅包含 'server'、'username'、'password' 的字典。

user_data_dir

用户数据目录的路径,用于保存 Cookie、本地存储等浏览器会话数据。默认创建临时目录。

extra_flags

启动浏览器时传入的额外参数列表。

selector_config

创建最终 Selector 对象时传入的参数。

additional_args

传给 Playwright 上下文的额外设置,优先级高于 Scrapling 设置。

返回 说明
Response

一个 Response 对象。

源代码位于 scrapling/fetchers/stealth_chrome.py
@classmethod
async def async_fetch(cls, url: str, **kwargs: Unpack[StealthSession]) -> Response:
    """
    Opens up a browser and do your request based on your chosen options below.

    :param url: Target url.
    :param headless: Run the browser in headless/hidden (default), or headful/visible mode.
    :param disable_resources: Drop requests for unnecessary resources for a speed boost.
        Requests dropped are of type `font`, `image`, `media`, `beacon`, `object`, `imageset`, `texttrack`, `websocket`, `csp_report`, and `stylesheet`.
    :param blocked_domains: A set of domain names to block requests to. Subdomains are also matched (e.g., ``"example.com"`` blocks ``"sub.example.com"`` too).
    :param block_ads: Block requests to ~3,500 known ad/tracking domains. Can be combined with ``blocked_domains``.
    :param dns_over_https: Route DNS queries through Cloudflare's DNS-over-HTTPS to prevent DNS leaks when using proxies.
    :param useragent: Pass a useragent string to be used. Otherwise the fetcher will generate a real Useragent of the same browser and use it.
    :param cookies: Set cookies for the next request.
    :param network_idle: Wait for the page until there are no network connections for at least 500 ms.
    :param timeout: The timeout in milliseconds that is used in all operations and waits through the page. The default is 30,000
    :param wait: The time (milliseconds) the fetcher will wait after everything finishes before closing the page and returning the ` Response ` object.
    :param page_action: Added for automation. A function that takes the `page` object, runs after navigation, and does the automation you need.
    :param page_setup: A function that takes the `page` object, runs before navigation. Use it to register event listeners or routes that must be set up before the page loads.
    :param wait_selector: Wait for a specific CSS selector to be in a specific state.
    :param init_script: An absolute path to a JavaScript file to be executed on page creation for all pages in this session.
    :param locale: Specify user locale, for example, `en-GB`, `de-DE`, etc. Locale will affect navigator.language value, Accept-Language request header value as well as number and date formatting
        rules. Defaults to the system default locale.
    :param timezone_id: Changes the timezone of the browser. Defaults to the system timezone.
    :param wait_selector_state: The state to wait for the selector given with `wait_selector`. The default state is `attached`.
    :param solve_cloudflare: Solves all types of the Cloudflare's Turnstile/Interstitial challenges before returning the response to you.
    :param real_chrome: If you have a Chrome browser installed on your device, enable this, and the Fetcher will launch an instance of your browser and use it.
    :param hide_canvas: Add random noise to canvas operations to prevent fingerprinting.
    :param block_webrtc: Forces WebRTC to respect proxy settings to prevent local IP address leak.
    :param allow_webgl: Enabled by default. Disabling it disables WebGL and WebGL 2.0 support entirely. Disabling WebGL is not recommended as many WAFs now check if WebGL is enabled.
    :param load_dom: Enabled by default, wait for all JavaScript on page(s) to fully load and execute.
    :param pierce_shadow: Include open Shadow DOM content in the response HTML. Defaults to False.
    :param google_search: Enabled by default, Scrapling will set a Google referer header.
    :param extra_headers: A dictionary of extra headers to add to the request. _The referer set by `google_search` takes priority over the referer set here if used together._
    :param proxy: The proxy to be used with requests, it can be a string or a dictionary with the keys 'server', 'username', and 'password' only.
    :param user_data_dir: Path to a User Data Directory, which stores browser session data like cookies and local storage. The default is to create a temporary directory.
    :param extra_flags: A list of additional browser flags to pass to the browser on launch.
    :param selector_config: The arguments that will be passed in the end while creating the final Selector's class.
    :param additional_args: Additional arguments to be passed to Playwright's context as additional settings, and it takes higher priority than Scrapling's settings.
    :return: A `Response` object.
    """
    selector_config = kwargs.get("selector_config", {}) or kwargs.get(
        "custom_config", {}
    )  # Checking `custom_config` for backward compatibility
    if not isinstance(selector_config, dict):
        raise TypeError("Argument `selector_config` must be a dictionary.")

    kwargs["selector_config"] = {**cls._generate_parser_arguments(), **selector_config}

    async with AsyncStealthySession(**kwargs) as engine:
        return await engine.fetch(url)

会话类

HTTP 会话

scrapling.fetchers.FetcherSession

FetcherSession(
    impersonate="chrome",
    http3=False,
    stealthy_headers=True,
    proxies=None,
    proxy=None,
    proxy_auth=None,
    timeout=30,
    headers=None,
    retries=3,
    retry_delay=1,
    follow_redirects="safe",
    max_redirects=30,
    verify=True,
    cert=None,
    selector_config=None,
    proxy_rotator=None,
)

创建已配置 Fetcher 会话的上下文管理器。

在 'with' 或 'async with' 代码块中使用时,这个管理器会提供一个采用默认配置的新会话。建议每个管理器实例同时只用于一个活动会话,或按顺序创建多个会话。已有会话运行时,不允许用同一个实例再次进入上下文。

参数 说明
impersonate

要模拟的浏览器版本。可以是单个浏览器字符串,或用于随机选择的字符串列表。默认使用最新可用的 Chrome 版本。

类型: ImpersonateType 默认值: 'chrome'

http3

是否使用 HTTP3,默认为 False。与 impersonate 同时使用可能出现问题。

类型: Optional[bool] 默认值: False

stealthy_headers

生成并添加真实浏览器请求头,包括 Google referer,默认开启。

类型: Optional[bool] 默认值: True

proxies

要使用的代理字典,格式为 {"http": proxy_url, "https": proxy_url}。

类型: Optional[Dict[str, str]] 默认值: None

proxy

要使用的代理 URL,格式为 "http://username:password@localhost:8030"。不能与 proxies 参数同时使用。

类型: Optional[str] 默认值: None

proxy_auth

代理的 HTTP Basic 认证,格式为 (username, password) 元组。

类型: Optional[Tuple[str, str]] 默认值: None

timeout

超时前等待的秒数。

类型: Optional[int | float] 默认值: 30

headers

会话中每次请求都会发送的请求头。

类型: Optional[Dict[str, str]] 默认值: None

retries

重试次数,默认为 3。

类型: Optional[int] 默认值: 3

retry_delay

重试之间的等待秒数,默认为 1 秒。

类型: Optional[int] 默认值: 1

follow_redirects

是否跟随重定向。默认为 "safe",跟随重定向但拒绝指向内部或私有 IP 的目标,以防范 SSRF。传入 True 可不受限制地跟随所有重定向。

类型: FollowRedirects 默认值: 'safe'

max_redirects

最大重定向次数,默认为 30,设为 -1 表示不限制。

类型: int 默认值: 30

verify

是否验证 HTTPS 证书,默认为 True。

类型: bool 默认值: True

cert

客户端证书和密钥的文件名元组,格式为 (cert, key)。

类型: Optional[str | Tuple[str, str]] 默认值: None

selector_config

创建最终 Selector 对象时传入的参数。

类型: Optional[Dict] 默认值: None

proxy_rotator

用于自动轮换代理的 ProxyRotator 实例。

类型: Optional[ProxyRotator] 默认值: None

源代码位于 scrapling/engines/static.py
def __init__(
    self,
    impersonate: ImpersonateType = "chrome",
    http3: Optional[bool] = False,
    stealthy_headers: Optional[bool] = True,
    proxies: Optional[Dict[str, str]] = None,
    proxy: Optional[str] = None,
    proxy_auth: Optional[Tuple[str, str]] = None,
    timeout: Optional[int | float] = 30,
    headers: Optional[Dict[str, str]] = None,
    retries: Optional[int] = 3,
    retry_delay: Optional[int] = 1,
    follow_redirects: FollowRedirects = "safe",
    max_redirects: int = 30,
    verify: bool = True,
    cert: Optional[str | Tuple[str, str]] = None,
    selector_config: Optional[Dict] = None,
    proxy_rotator: Optional[ProxyRotator] = None,
):
    """
    :param impersonate: Browser version to impersonate. Can be a single browser string or a list of browser strings for random selection. (Default: latest available Chrome version)
    :param http3: Whether to use HTTP3. Defaults to False. It might be problematic if used it with `impersonate`.
    :param stealthy_headers: If enabled (default), it creates and adds real browser headers. It also sets a Google referer header.
    :param proxies: Dict of proxies to use. Format: {"http": proxy_url, "https": proxy_url}.
    :param proxy: Proxy URL to use. Format: "http://username:password@localhost:8030".
                 Cannot be used together with the `proxies` parameter.
    :param proxy_auth: HTTP basic auth for proxy, tuple of (username, password).
    :param timeout: Number of seconds to wait before timing out.
    :param headers: Headers to include in the session with every request.
    :param retries: Number of retry attempts. Defaults to 3.
    :param retry_delay: Number of seconds to wait between retry attempts. Defaults to 1 second.
    :param follow_redirects: Whether to follow redirects. Defaults to "safe", which follows redirects but rejects those targeting internal/private IPs (SSRF protection). Pass True to follow all redirects without restriction.
    :param max_redirects: Maximum number of redirects. Default 30, use -1 for unlimited.
    :param verify: Whether to verify HTTPS certificates. Defaults to True.
    :param cert: Tuple of (cert, key) filenames for the client certificate.
    :param selector_config: Arguments passed when creating the final Selector class.
    :param proxy_rotator: A ProxyRotator instance for automatic proxy rotation.
    """
    self._default_impersonate: ImpersonateType = impersonate
    self._stealth = stealthy_headers
    self._default_proxies = proxies or {}
    self._default_proxy = proxy or None
    self._default_proxy_auth = proxy_auth or None
    self._default_timeout = timeout
    self._default_headers = headers or {}
    self._default_retries = retries
    self._default_retry_delay = retry_delay
    self._default_follow_redirects = follow_redirects
    self._default_max_redirects = max_redirects
    self._default_verify = verify
    self._default_cert = cert
    self._default_http3 = http3
    self.selector_config = selector_config or {}
    self._is_alive = False
    self._client: _SyncSessionLogic | _ASyncSessionLogic | None = None
    self._proxy_rotator = proxy_rotator

__slots__ class-attribute instance-attribute

__slots__ = (
    "_default_impersonate",
    "_stealth",
    "_default_proxies",
    "_default_proxy",
    "_default_proxy_auth",
    "_default_timeout",
    "_default_headers",
    "_default_retries",
    "_default_retry_delay",
    "_default_follow_redirects",
    "_default_max_redirects",
    "_default_verify",
    "_default_cert",
    "_default_http3",
    "selector_config",
    "_client",
    "_is_alive",
    "_proxy_rotator",
)

selector_config instance-attribute

selector_config = selector_config or {}

__enter__

__enter__()

创建并返回新的同步 Fetcher 会话。

源代码位于 scrapling/engines/static.py
def __enter__(self) -> _SyncSessionLogic:
    """Creates and returns a new synchronous Fetcher Session"""
    if self._client is None:
        # Use **vars(self) to avoid repeating all parameters
        config = {k.replace("_default_", ""): getattr(self, k) for k in self.__slots__ if k.startswith("_default")}
        config["stealthy_headers"] = self._stealth
        config["selector_config"] = self.selector_config
        config["proxy_rotator"] = self._proxy_rotator
        self._client = _SyncSessionLogic(**config)
        try:
            result = self._client.__enter__()
        except Exception:
            self._client = None
            raise
        self._is_alive = True
        return result
    raise RuntimeError("This FetcherSession instance already has an active synchronous session.")

__exit__

__exit__(exc_type, exc_val, exc_tb)
源代码位于 scrapling/engines/static.py
def __exit__(self, exc_type, exc_val, exc_tb):
    if self._client is not None and isinstance(self._client, _SyncSessionLogic):
        self._client.__exit__(exc_type, exc_val, exc_tb)
        self._client = None
        self._is_alive = False
        return
    raise RuntimeError("Cannot exit invalid session")

__aenter__ async

__aenter__()

创建并返回新的异步会话。

源代码位于 scrapling/engines/static.py
async def __aenter__(self) -> _ASyncSessionLogic:
    """Creates and returns a new asynchronous Session."""
    if self._client is None:
        # Use **vars(self) to avoid repeating all parameters
        config = {k.replace("_default_", ""): getattr(self, k) for k in self.__slots__ if k.startswith("_default")}
        config["stealthy_headers"] = self._stealth
        config["selector_config"] = self.selector_config
        config["proxy_rotator"] = self._proxy_rotator
        self._client = _ASyncSessionLogic(**config)
        try:
            result = await self._client.__aenter__()
        except Exception:
            self._client = None
            raise
        self._is_alive = True
        return result
    raise RuntimeError("This FetcherSession instance already has an active asynchronous session.")

__aexit__ async

__aexit__(exc_type, exc_val, exc_tb)
源代码位于 scrapling/engines/static.py
async def __aexit__(self, exc_type, exc_val, exc_tb):
    if self._client is not None and isinstance(self._client, _ASyncSessionLogic):
        await self._client.__aexit__(exc_type, exc_val, exc_tb)
        self._client = None
        self._is_alive = False
        return
    raise RuntimeError("Cannot exit invalid session")

隐身浏览器会话

scrapling.fetchers.StealthySession

StealthySession(**kwargs)

基类: SyncSession, StealthySessionMixin


              flowchart TD
              scrapling.fetchers.StealthySession[StealthySession]
              scrapling.engines._browsers._base.SyncSession[SyncSession]
              scrapling.engines._browsers._base.StealthySessionMixin[StealthySessionMixin]
              scrapling.engines._browsers._base.BaseSessionMixin[BaseSessionMixin]

                              scrapling.engines._browsers._base.SyncSession --> scrapling.fetchers.StealthySession
                
                scrapling.engines._browsers._base.StealthySessionMixin --> scrapling.fetchers.StealthySession
                                scrapling.engines._browsers._base.BaseSessionMixin --> scrapling.engines._browsers._base.StealthySessionMixin
                



              click scrapling.fetchers.StealthySession href "" "scrapling.fetchers.StealthySession"
              click scrapling.engines._browsers._base.SyncSession href "" "scrapling.engines._browsers._base.SyncSession"
              click scrapling.engines._browsers._base.StealthySessionMixin href "" "scrapling.engines._browsers._base.StealthySessionMixin"
              click scrapling.engines._browsers._base.BaseSessionMixin href "" "scrapling.engines._browsers._base.BaseSessionMixin"
            

使用页面池的隐身浏览器会话管理器。

使用页面池的浏览器会话管理器。默认使用持久浏览器上下文和临时用户配置目录。

参数 说明
record_requests

保存已完成的浏览器请求和响应。失败或尚未完成的请求会被省略,默认为 False。

max_recorded_requests

每个会话最多保留的请求数,默认为 1,000,旧条目会被移除。

headless

以无头模式运行,不显示窗口,这是默认设置;也可以显示浏览器窗口。

disable_resources

阻止不必要的资源请求以提高速度。类型包括 font、image、media、beacon、object、imageset、texttrack、websocket、csp_report 和 stylesheet。

blocked_domains

要阻止请求的域名集合,也会匹配子域名。例如,"example.com" 也会阻止 "sub.example.com"。

useragent

指定 User-Agent 字符串。未指定时,Fetcher 会生成并使用相同浏览器的真实 User-Agent。

cookies

为下一次请求设置 Cookie。

network_idle

等待页面至少连续 500 ms 没有网络连接。

timeout

页面所有操作和等待的超时时间,单位为毫秒,默认为 30,000。

wait

所有步骤完成后,在关闭页面并返回 Response 对象前额外等待的时间,单位为毫秒。

page_action

用于自动化的函数,接收 page 对象,在导航后执行所需操作。

page_setup

接收 page 对象并在导航前执行的函数。用于注册必须在页面加载前准备好的事件监听器或路由。

wait_selector

等待指定 CSS 选择器达到指定状态。

init_script

JavaScript 文件的绝对路径,在此会话中的每个页面创建时执行。

locale

区域设置,例如 en-GB、de-DE。影响 navigator.language、请求头 Accept-Language,以及数字和日期格式。默认使用系统区域设置。

timezone_id

修改浏览器时区,默认使用系统时区。

wait_selector_state

等待 wait_selector 指定的元素达到这个状态。默认为 attached。

solve_cloudflare

返回响应前,处理所有类型的 Cloudflare Turnstile 和 Interstitial 挑战。

real_chrome

如果设备上已安装 Chrome,启用此选项后,Fetcher 会启动并使用它。

hide_canvas

为 Canvas 操作添加随机噪声,防止指纹识别。

block_webrtc

强制 WebRTC 遵守代理设置,避免泄露本地 IP 地址。

allow_webgl

默认开启。关闭后会完全禁用 WebGL 和 WebGL 2.0。不建议关闭,因为很多 WAF 会检查 WebGL 是否启用。

load_dom

等待页面上的所有 JavaScript 加载并执行,默认开启。

pierce_shadow

将开放的 Shadow DOM 内容加入响应 HTML,默认为 False。

google_search

默认开启,Scrapling 会设置 Google referer 请求头。

extra_headers

要添加到请求中的额外请求头字典。同时使用时,google_search 设置的 referer 优先于这里的值。

proxy

请求使用的代理,可以是字符串,或仅包含 'server'、'username'、'password' 的字典。

user_data_dir

用户数据目录的路径,用于保存 Cookie、本地存储等浏览器会话数据。默认创建临时目录。

extra_flags

启动浏览器时传入的额外参数列表。

selector_config

创建最终 Selector 对象时传入的参数。

additional_args

传给 Playwright 上下文的额外设置,优先级高于 Scrapling 设置。

源代码位于 scrapling/engines/_browsers/_stealth.py
def __init__(self, **kwargs: Unpack[StealthSession]):
    """A Browser session manager with page pooling, it's using a persistent browser Context by default with a temporary user profile directory.

    :param record_requests: Save completed browser requests and responses. Failed or unfinished requests are omitted. Defaults to False.
    :param max_recorded_requests: Maximum retained requests per session. Defaults to 1000; older entries are removed.
    :param headless: Run the browser in headless/hidden (default), or headful/visible mode.
    :param disable_resources: Drop requests for unnecessary resources for a speed boost.
        Requests dropped are of type `font`, `image`, `media`, `beacon`, `object`, `imageset`, `texttrack`, `websocket`, `csp_report`, and `stylesheet`.
    :param blocked_domains: A set of domain names to block requests to. Subdomains are also matched (e.g., ``"example.com"`` blocks ``"sub.example.com"`` too).
    :param useragent: Pass a useragent string to be used. Otherwise the fetcher will generate a real Useragent of the same browser and use it.
    :param cookies: Set cookies for the next request.
    :param network_idle: Wait for the page until there are no network connections for at least 500 ms.
    :param timeout: The timeout in milliseconds that is used in all operations and waits through the page. The default is 30,000
    :param wait: The time (milliseconds) the fetcher will wait after everything finishes before closing the page and returning the ` Response ` object.
    :param page_action: Added for automation. A function that takes the `page` object, runs after navigation, and does the automation you need.
    :param page_setup: A function that takes the `page` object, runs before navigation. Use it to register event listeners or routes that must be set up before the page loads.
    :param wait_selector: Wait for a specific CSS selector to be in a specific state.
    :param init_script: An absolute path to a JavaScript file to be executed on page creation for all pages in this session.
    :param locale: Specify user locale, for example, `en-GB`, `de-DE`, etc. Locale will affect navigator.language value, Accept-Language request header value as well as number and date formatting
        rules. Defaults to the system default locale.
    :param timezone_id: Changes the timezone of the browser. Defaults to the system timezone.
    :param wait_selector_state: The state to wait for the selector given with `wait_selector`. The default state is `attached`.
    :param solve_cloudflare: Solves all types of the Cloudflare's Turnstile/Interstitial challenges before returning the response to you.
    :param real_chrome: If you have a Chrome browser installed on your device, enable this, and the Fetcher will launch an instance of your browser and use it.
    :param hide_canvas: Add random noise to canvas operations to prevent fingerprinting.
    :param block_webrtc: Forces WebRTC to respect proxy settings to prevent local IP address leak.
    :param allow_webgl: Enabled by default. Disabling it disables WebGL and WebGL 2.0 support entirely. Disabling WebGL is not recommended as many WAFs now check if WebGL is enabled.
    :param load_dom: Enabled by default, wait for all JavaScript on page(s) to fully load and execute.
    :param pierce_shadow: Include open Shadow DOM content in the response HTML. Defaults to False.
    :param google_search: Enabled by default, Scrapling will set a Google referer header.
    :param extra_headers: A dictionary of extra headers to add to the request. _The referer set by `google_search` takes priority over the referer set here if used together._
    :param proxy: The proxy to be used with requests, it can be a string or a dictionary with the keys 'server', 'username', and 'password' only.
    :param user_data_dir: Path to a User Data Directory, which stores browser session data like cookies and local storage. The default is to create a temporary directory.
    :param extra_flags: A list of additional browser flags to pass to the browser on launch.
    :param selector_config: The arguments that will be passed in the end while creating the final Selector's class.
    :param additional_args: Additional arguments to be passed to Playwright's context as additional settings, and it takes higher priority than Scrapling's settings.
    """
    self.__validate__(**kwargs)
    super().__init__(
        record_requests=self._config.record_requests,
        max_recorded_requests=self._config.max_recorded_requests,
    )

max_pages instance-attribute

max_pages = max_pages

network instance-attribute

network = NetworkRecorder(
    enabled=record_requests,
    max_requests=max_recorded_requests,
)

page_pool instance-attribute

page_pool = PagePool(max_pages)

playwright instance-attribute

playwright = None

context instance-attribute

context = None

browser instance-attribute

browser = None

__slots__ class-attribute instance-attribute

__slots__ = (
    "_config",
    "_context_options",
    "_browser_options",
    "_user_data_dir",
    "_headers_keys",
    "max_pages",
    "page_pool",
    "_max_wait_for_page",
    "playwright",
    "context",
)

__validate_routine__

__validate_routine__(params, model)
源代码位于 scrapling/engines/_browsers/_base.py
def __validate_routine__(
    self, params: Dict, model: type[PlaywrightConfig] | type[StealthConfig]
) -> PlaywrightConfig | StealthConfig:
    # Dark color scheme bypasses the 'prefersLightColor' check in creepjs
    self._context_options: Dict[str, Any] = {"color_scheme": "dark", "device_scale_factor": 2}
    self._browser_options: Dict[str, Any] = {
        "args": DEFAULT_ARGS,
        "ignore_default_args": HARMFUL_ARGS,
    }
    if "__max_pages" in params:
        params["max_pages"] = params.pop("__max_pages")

    config = validate(params, model=model)
    self._headers_keys = (
        {header.lower() for header in config.extra_headers.keys()} if config.extra_headers else set()
    )

    return config

__generate_context_options__

__generate_context_options__()
源代码位于 scrapling/engines/_browsers/_base.py
def __generate_context_options__(self) -> None:
    config: PlaywrightConfig | StealthConfig = self._config
    self._context_options.update(
        {
            "proxy": config.proxy,
            "timezone_id": config.timezone_id,
            "extra_http_headers": config.extra_headers,
        }
    )
    # The default useragent in the headful is always correct now in the current versions of Playwright
    if config.useragent:
        self._context_options["user_agent"] = config.useragent
    elif not config.useragent and config.headless:
        self._context_options["user_agent"] = (
            __default_chrome_useragent__ if config.real_chrome else __default_useragent__
        )

    if config.additional_args:
        self._context_options.update(config.additional_args)

__generate_options__

__generate_options__(extra_flags=None)
源代码位于 scrapling/engines/_browsers/_base.py
def __generate_options__(self, extra_flags: Tuple | None = None) -> None:
    self.__generate_context_options__()
    config = self._config
    flags = self._browser_options["args"]
    if config.extra_flags or extra_flags:
        flags = list(set(tuple(flags) + tuple(extra_flags or ()) + tuple(config.extra_flags or ())))
    if config.dns_over_https:
        flags = list(flags) + ["--dns-over-https-templates=https://cloudflare-dns.com/dns-query"]
    if config.locale:
        base_lang = config.locale.split("-")[0].lower()
        accept_lang = f"{config.locale},{base_lang}" if base_lang != config.locale.lower() else config.locale
        flags = list(flags) + [f"--lang={config.locale}", f"--accept-lang={accept_lang}"]
    self._browser_options.update(
        {"args": flags, "headless": config.headless, "channel": "chrome" if config.real_chrome else "chromium"}
    )
    if config.executable_path:
        self._browser_options["executable_path"] = config.executable_path
    self._user_data_dir = config.user_data_dir

__validate__

__validate__(**params)
源代码位于 scrapling/engines/_browsers/_base.py
def __validate__(self, **params):
    self._config = self.__validate_routine__(params, model=self._config_class)
    self._context_options.update(
        {
            "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"],
        }
    )
    self.__generate_stealth_options()

save_state

save_state(path)

将 Cookie、本地存储和 IndexedDB 保存到与 Playwright 兼容的 JSON 文件。

需要已启动且未启用代理轮换的会话。不保存 sessionStorage。

源代码位于 scrapling/engines/_browsers/_base.py
def save_state(self, path: str | Path) -> None:
    """Save cookies, local storage and IndexedDB to a Playwright-compatible JSON file.

    Requires a started session without proxy rotation. Does not save sessionStorage.
    """
    if not self._is_alive or self.context is None:
        raise RuntimeError("Session state requires a started browser session without proxy rotation")
    self.context.storage_state(path=Path(path), indexed_db=True)

load_state

load_state(path)

使用与 Playwright 兼容的 JSON 文件替换 Cookie、本地存储和 IndexedDB。

需要已启动且未启用代理轮换的会话。获取或重新加载页面后,才能使用恢复的登录状态。

源代码位于 scrapling/engines/_browsers/_base.py
def load_state(self, path: str | Path) -> None:
    """Replace cookies, local storage and IndexedDB from a Playwright-compatible JSON file.

    Requires a started session without proxy rotation. Fetch or reload pages to use the restored login.
    """
    if not self._is_alive or self.context is None:
        raise RuntimeError("Session state requires a started browser session without proxy rotation")
    self.context.set_storage_state(path)

close_pages

close_pages()

关闭会话池中的所有标签页。下一次请求会打开新的标签页。

源代码位于 scrapling/engines/_browsers/_base.py
def close_pages(self) -> None:
    """Close every open tab in the session's pool. The next request opens a fresh tab."""
    for page_info in self.page_pool.clear():
        with suppress(Exception):
            page_info.page.close()

close

close()

关闭所有资源。

源代码位于 scrapling/engines/_browsers/_base.py
def close(self):  # pragma: no cover
    """Close all resources"""
    self.network._detach()
    if not self._is_alive:
        return

    self.close_pages()
    try:
        if self.context and self._owns_context:
            self.context.close()
    finally:
        self.context = None
        try:
            if self.browser:
                self.browser.close()
        finally:
            self.browser = None
            try:
                if self.playwright:
                    self.playwright.stop()
            finally:
                self.playwright = None
                self._is_alive = False

__enter__

__enter__()
源代码位于 scrapling/engines/_browsers/_base.py
def __enter__(self):
    self.start()
    return self

__exit__

__exit__(exc_type, exc_val, exc_tb)
源代码位于 scrapling/engines/_browsers/_base.py
def __exit__(self, exc_type, exc_val, exc_tb):
    self.close()

get_pool_stats

get_pool_stats()

获取当前页面池的统计信息。

源代码位于 scrapling/engines/_browsers/_base.py
def get_pool_stats(self) -> Dict[str, int]:
    """Get statistics about the current page pool"""
    return {
        "total_pages": self.page_pool.pages_count,
        "busy_pages": self.page_pool.busy_count,
        "max_pages": self.max_pages,
    }

start

start()

为此实例及上下文创建浏览器。

源代码位于 scrapling/engines/_browsers/_stealth.py
def start(self) -> None:
    """Create a browser for this instance and context."""
    if not self.playwright:
        self.playwright = sync_playwright().start()
        self._is_alive = True
        try:
            self._create_context()
            if self.context:
                self.context = self._initialize_context(self._config, self.context)
        except BaseException:
            with suppress(Exception):
                self.close()
            raise
    else:
        raise RuntimeError("Session has been already started")

fetch

fetch(url, **kwargs)

打开浏览器,按所选选项发送请求。

参数 说明
url

目标 URL。

类型: str

google_search

默认开启,Scrapling 会设置 Google referer 请求头。

timeout

页面所有操作和等待的超时时间,单位为毫秒,默认为 30,000。

wait

所有步骤完成后,在关闭页面并返回 Response 对象前额外等待的时间,单位为毫秒。

page_action

用于自动化的函数,接收 page 对象,在导航后执行所需操作。

page_setup

接收 page 对象并在导航前执行的函数。用于注册必须在页面加载前准备好的事件监听器或路由。

extra_headers

要添加到请求中的额外请求头字典。同时使用时,google_search 设置的 referer 优先于这里的值。

disable_resources

阻止不必要的资源请求以提高速度。类型包括 font、image、media、beacon、object、imageset、texttrack、websocket、csp_report 和 stylesheet。

blocked_domains

要阻止请求的域名集合,也会匹配子域名。例如,"example.com" 也会阻止 "sub.example.com"。

wait_selector

等待指定 CSS 选择器达到指定状态。

wait_selector_state

等待 wait_selector 指定的元素达到这个状态。默认为 attached。

network_idle

等待页面至少连续 500 ms 没有网络连接。

load_dom

等待页面上的所有 JavaScript 加载并执行,默认开启。

pierce_shadow

将开放的 Shadow DOM 内容加入响应 HTML,默认为 False。

solve_cloudflare

返回响应前,处理所有类型的 Cloudflare Turnstile 和 Interstitial 挑战。

selector_config

创建最终 Selector 对象时传入的参数。

proxy

覆盖代理轮换器和会话代理的固定代理。会为它创建并使用新的浏览器上下文。

返回 说明
Response

一个 Response 对象。

源代码位于 scrapling/engines/_browsers/_stealth.py
def fetch(self, url: str, **kwargs: Unpack[StealthFetchParams]) -> Response:
    """Opens up the browser and do your request based on your chosen options.

    :param url: The Target url.
    :param google_search: Enabled by default, Scrapling will set a Google referer header.
    :param timeout: The timeout in milliseconds that is used in all operations and waits through the page. The default is 30,000
    :param wait: The time (milliseconds) the fetcher will wait after everything finishes before closing the page and returning the ` Response ` object.
    :param page_action: Added for automation. A function that takes the `page` object, runs after navigation, and does the automation you need.
    :param page_setup: A function that takes the `page` object, runs before navigation. Use it to register event listeners or routes that must be set up before the page loads.
    :param extra_headers: A dictionary of extra headers to add to the request. _The referer set by `google_search` takes priority over the referer set here if used together._
    :param disable_resources: Drop requests for unnecessary resources for a speed boost.
        Requests dropped are of type `font`, `image`, `media`, `beacon`, `object`, `imageset`, `texttrack`, `websocket`, `csp_report`, and `stylesheet`.
    :param blocked_domains: A set of domain names to block requests to. Subdomains are also matched (e.g., ``"example.com"`` blocks ``"sub.example.com"`` too).
    :param wait_selector: Wait for a specific CSS selector to be in a specific state.
    :param wait_selector_state: The state to wait for the selector given with `wait_selector`. The default state is `attached`.
    :param network_idle: Wait for the page until there are no network connections for at least 500 ms.
    :param load_dom: Enabled by default, wait for all JavaScript on page(s) to fully load and execute.
    :param pierce_shadow: Include open Shadow DOM content in the response HTML. Defaults to False.
    :param solve_cloudflare: Solves all types of the Cloudflare's Turnstile/Interstitial challenges before returning the response to you.
    :param selector_config: The arguments that will be passed in the end while creating the final Selector's class.
    :param proxy: Static proxy to override rotator and session proxy. A new browser context will be created and used with it.
    :return: A `Response` object.
    """
    static_proxy = kwargs.pop("proxy", None)
    if not self._owns_context:
        static_proxy = None

    params = _validate(kwargs, self, StealthConfig)
    if not self._is_alive:  # pragma: no cover
        raise RuntimeError("Context manager has been closed")

    request_headers_keys = {h.lower() for h in params.extra_headers.keys()} if params.extra_headers else set()
    referer = (
        "https://www.google.com/" if (params.google_search and "referer" not in request_headers_keys) else None
    )

    for attempt in range(self._config.retries):
        proxy: Optional[ProxyType] = None
        if self._config.proxy_rotator and static_proxy is None:
            proxy = self._config.proxy_rotator.get_proxy()
        else:
            proxy = static_proxy

        with self._page_generator(
            params.timeout, params.extra_headers, params.disable_resources, proxy, params.blocked_domains
        ) as page_info:
            final_response: List = [None]
            page = page_info.page
            handler = self._create_response_handler(page_info, final_response)
            page.on("response", handler)
            try:
                if params.page_setup:
                    try:
                        params.page_setup(page)
                    except Exception as e:  # pragma: no cover
                        log.error(f"Error executing page_setup: {e}")

                try:
                    first_response = page.goto(url, referer=referer)
                    self._wait_for_page_stability(page, params.load_dom, params.network_idle)

                    if not first_response:
                        raise RuntimeError(f"Failed to get response for {url}")

                    if params.solve_cloudflare:
                        self._cloudflare_solver(page)
                        # Make sure the page is fully loaded after the captcha
                        self._wait_for_page_stability(page, params.load_dom, params.network_idle)

                    if params.page_action:
                        try:
                            _ = params.page_action(page)
                        except Exception as e:  # pragma: no cover
                            log.error(f"Error executing page_action: {e}")

                    if params.wait_selector:
                        try:
                            waiter: Locator = page.locator(params.wait_selector)
                            waiter.first.wait_for(state=params.wait_selector_state)
                            self._wait_for_page_stability(page, params.load_dom, params.network_idle)
                        except Exception as e:  # pragma: no cover
                            log.error(f"Error waiting for selector {params.wait_selector}: {e}")

                    page.wait_for_timeout(params.wait)

                    response = ResponseFactory.from_playwright_response(
                        page,
                        first_response,
                        final_response[0],
                        params.selector_config,
                        meta={"proxy": proxy},
                        pierce_shadow=params.pierce_shadow,
                    )
                    return response

                except Exception as e:
                    page_info.mark_error()
                    if attempt < self._config.retries - 1:
                        if is_proxy_error(e):
                            log.warning(
                                f"Proxy '{proxy}' failed (attempt {attempt + 1}) | Retrying in {self._config.retry_delay}s..."
                            )
                        else:
                            log.warning(
                                f"Attempt {attempt + 1} failed: {e}. Retrying in {self._config.retry_delay}s..."
                            )
                        time_sleep(self._config.retry_delay)
                    else:
                        log.error(f"Failed after {self._config.retries} attempts: {e}")
                        raise
            finally:
                page.remove_listener("response", handler)

    raise RuntimeError("Request failed")  # pragma: no cover

scrapling.fetchers.AsyncStealthySession

AsyncStealthySession(**kwargs)

基类: AsyncSession, StealthySessionMixin


              flowchart TD
              scrapling.fetchers.AsyncStealthySession[AsyncStealthySession]
              scrapling.engines._browsers._base.AsyncSession[AsyncSession]
              scrapling.engines._browsers._base.StealthySessionMixin[StealthySessionMixin]
              scrapling.engines._browsers._base.BaseSessionMixin[BaseSessionMixin]

                              scrapling.engines._browsers._base.AsyncSession --> scrapling.fetchers.AsyncStealthySession
                
                scrapling.engines._browsers._base.StealthySessionMixin --> scrapling.fetchers.AsyncStealthySession
                                scrapling.engines._browsers._base.BaseSessionMixin --> scrapling.engines._browsers._base.StealthySessionMixin
                



              click scrapling.fetchers.AsyncStealthySession href "" "scrapling.fetchers.AsyncStealthySession"
              click scrapling.engines._browsers._base.AsyncSession href "" "scrapling.engines._browsers._base.AsyncSession"
              click scrapling.engines._browsers._base.StealthySessionMixin href "" "scrapling.engines._browsers._base.StealthySessionMixin"
              click scrapling.engines._browsers._base.BaseSessionMixin href "" "scrapling.engines._browsers._base.BaseSessionMixin"
            

使用页面池的异步隐身浏览器会话管理器。

使用页面池的浏览器会话管理器。默认使用持久浏览器上下文和临时用户配置目录。

参数 说明
record_requests

保存已完成的浏览器请求和响应。失败或尚未完成的请求会被省略,默认为 False。

max_recorded_requests

每个会话最多保留的请求数,默认为 1,000,旧条目会被移除。

headless

以无头模式运行,不显示窗口,这是默认设置;也可以显示浏览器窗口。

disable_resources

阻止不必要的资源请求以提高速度。类型包括 font、image、media、beacon、object、imageset、texttrack、websocket、csp_report 和 stylesheet。

blocked_domains

要阻止请求的域名集合,也会匹配子域名。例如,"example.com" 也会阻止 "sub.example.com"。

useragent

指定 User-Agent 字符串。未指定时,Fetcher 会生成并使用相同浏览器的真实 User-Agent。

cookies

为下一次请求设置 Cookie。

network_idle

等待页面至少连续 500 ms 没有网络连接。

timeout

页面所有操作和等待的超时时间,单位为毫秒,默认为 30,000。

wait

所有步骤完成后,在关闭页面并返回 Response 对象前额外等待的时间,单位为毫秒。

page_action

用于自动化的函数,接收 page 对象,在导航后执行所需操作。

page_setup

接收 page 对象并在导航前执行的函数。用于注册必须在页面加载前准备好的事件监听器或路由。

wait_selector

等待指定 CSS 选择器达到指定状态。

init_script

JavaScript 文件的绝对路径,在此会话中的每个页面创建时执行。

locale

区域设置,例如 en-GB、de-DE。影响 navigator.language、请求头 Accept-Language,以及数字和日期格式。默认使用系统区域设置。

timezone_id

修改浏览器时区,默认使用系统时区。

wait_selector_state

等待 wait_selector 指定的元素达到这个状态。默认为 attached。

solve_cloudflare

返回响应前,处理所有类型的 Cloudflare Turnstile 和 Interstitial 挑战。

real_chrome

如果设备上已安装 Chrome,启用此选项后,Fetcher 会启动并使用它。

hide_canvas

为 Canvas 操作添加随机噪声,防止指纹识别。

block_webrtc

强制 WebRTC 遵守代理设置,避免泄露本地 IP 地址。

allow_webgl

默认开启。关闭后会完全禁用 WebGL 和 WebGL 2.0。不建议关闭,因为很多 WAF 会检查 WebGL 是否启用。

load_dom

等待页面上的所有 JavaScript 加载并执行,默认开启。

pierce_shadow

将开放的 Shadow DOM 内容加入响应 HTML,默认为 False。

google_search

默认开启,Scrapling 会设置 Google referer 请求头。

extra_headers

要添加到请求中的额外请求头字典。同时使用时,google_search 设置的 referer 优先于这里的值。

proxy

请求使用的代理,可以是字符串,或仅包含 'server'、'username'、'password' 的字典。

user_data_dir

用户数据目录的路径,用于保存 Cookie、本地存储等浏览器会话数据。默认创建临时目录。

extra_flags

启动浏览器时传入的额外参数列表。

selector_config

创建最终 Selector 对象时传入的参数。

additional_args

传给 Playwright 上下文的额外设置,优先级高于 Scrapling 设置。

源代码位于 scrapling/engines/_browsers/_stealth.py
def __init__(self, **kwargs: Unpack[StealthSession]):
    """A Browser session manager with page pooling, it's using a persistent browser Context by default with a temporary user profile directory.

    :param record_requests: Save completed browser requests and responses. Failed or unfinished requests are omitted. Defaults to False.
    :param max_recorded_requests: Maximum retained requests per session. Defaults to 1000; older entries are removed.
    :param headless: Run the browser in headless/hidden (default), or headful/visible mode.
    :param disable_resources: Drop requests for unnecessary resources for a speed boost.
        Requests dropped are of type `font`, `image`, `media`, `beacon`, `object`, `imageset`, `texttrack`, `websocket`, `csp_report`, and `stylesheet`.
    :param blocked_domains: A set of domain names to block requests to. Subdomains are also matched (e.g., ``"example.com"`` blocks ``"sub.example.com"`` too).
    :param useragent: Pass a useragent string to be used. Otherwise the fetcher will generate a real Useragent of the same browser and use it.
    :param cookies: Set cookies for the next request.
    :param network_idle: Wait for the page until there are no network connections for at least 500 ms.
    :param timeout: The timeout in milliseconds that is used in all operations and waits through the page. The default is 30,000
    :param wait: The time (milliseconds) the fetcher will wait after everything finishes before closing the page and returning the ` Response ` object.
    :param page_action: Added for automation. A function that takes the `page` object, runs after navigation, and does the automation you need.
    :param page_setup: A function that takes the `page` object, runs before navigation. Use it to register event listeners or routes that must be set up before the page loads.
    :param wait_selector: Wait for a specific CSS selector to be in a specific state.
    :param init_script: An absolute path to a JavaScript file to be executed on page creation for all pages in this session.
    :param locale: Specify user locale, for example, `en-GB`, `de-DE`, etc. Locale will affect navigator.language value, Accept-Language request header value as well as number and date formatting
        rules. Defaults to the system default locale.
    :param timezone_id: Changes the timezone of the browser. Defaults to the system timezone.
    :param wait_selector_state: The state to wait for the selector given with `wait_selector`. The default state is `attached`.
    :param solve_cloudflare: Solves all types of the Cloudflare's Turnstile/Interstitial challenges before returning the response to you.
    :param real_chrome: If you have a Chrome browser installed on your device, enable this, and the Fetcher will launch an instance of your browser and use it.
    :param hide_canvas: Add random noise to canvas operations to prevent fingerprinting.
    :param block_webrtc: Forces WebRTC to respect proxy settings to prevent local IP address leak.
    :param allow_webgl: Enabled by default. Disabling it disables WebGL and WebGL 2.0 support entirely. Disabling WebGL is not recommended as many WAFs now check if WebGL is enabled.
    :param load_dom: Enabled by default, wait for all JavaScript on page(s) to fully load and execute.
    :param pierce_shadow: Include open Shadow DOM content in the response HTML. Defaults to False.
    :param google_search: Enabled by default, Scrapling will set a Google referer header.
    :param extra_headers: A dictionary of extra headers to add to the request. _The referer set by `google_search` takes priority over the referer set here if used together._
    :param proxy: The proxy to be used with requests, it can be a string or a dictionary with the keys 'server', 'username', and 'password' only.
    :param user_data_dir: Path to a User Data Directory, which stores browser session data like cookies and local storage. The default is to create a temporary directory.
    :param extra_flags: A list of additional browser flags to pass to the browser on launch.
    :param selector_config: The arguments that will be passed in the end while creating the final Selector's class.
    :param additional_args: Additional arguments to be passed to Playwright's context as additional settings, and it takes higher priority than Scrapling's settings.
    """
    self.__validate__(**kwargs)
    super().__init__(
        max_pages=self._config.max_pages,
        record_requests=self._config.record_requests,
        max_recorded_requests=self._config.max_recorded_requests,
    )

max_pages instance-attribute

max_pages = max_pages

network instance-attribute

network = NetworkRecorder(
    enabled=record_requests,
    max_requests=max_recorded_requests,
    asynchronous=True,
)

page_pool instance-attribute

page_pool = PagePool(max_pages)

playwright instance-attribute

playwright = None

context instance-attribute

context = None

browser instance-attribute

browser = None

__slots__ class-attribute instance-attribute

__slots__ = (
    "_config",
    "_context_options",
    "_browser_options",
    "_user_data_dir",
    "_headers_keys",
)

__validate_routine__

__validate_routine__(params, model)
源代码位于 scrapling/engines/_browsers/_base.py
def __validate_routine__(
    self, params: Dict, model: type[PlaywrightConfig] | type[StealthConfig]
) -> PlaywrightConfig | StealthConfig:
    # Dark color scheme bypasses the 'prefersLightColor' check in creepjs
    self._context_options: Dict[str, Any] = {"color_scheme": "dark", "device_scale_factor": 2}
    self._browser_options: Dict[str, Any] = {
        "args": DEFAULT_ARGS,
        "ignore_default_args": HARMFUL_ARGS,
    }
    if "__max_pages" in params:
        params["max_pages"] = params.pop("__max_pages")

    config = validate(params, model=model)
    self._headers_keys = (
        {header.lower() for header in config.extra_headers.keys()} if config.extra_headers else set()
    )

    return config

__generate_context_options__

__generate_context_options__()
源代码位于 scrapling/engines/_browsers/_base.py
def __generate_context_options__(self) -> None:
    config: PlaywrightConfig | StealthConfig = self._config
    self._context_options.update(
        {
            "proxy": config.proxy,
            "timezone_id": config.timezone_id,
            "extra_http_headers": config.extra_headers,
        }
    )
    # The default useragent in the headful is always correct now in the current versions of Playwright
    if config.useragent:
        self._context_options["user_agent"] = config.useragent
    elif not config.useragent and config.headless:
        self._context_options["user_agent"] = (
            __default_chrome_useragent__ if config.real_chrome else __default_useragent__
        )

    if config.additional_args:
        self._context_options.update(config.additional_args)

__generate_options__

__generate_options__(extra_flags=None)
源代码位于 scrapling/engines/_browsers/_base.py
def __generate_options__(self, extra_flags: Tuple | None = None) -> None:
    self.__generate_context_options__()
    config = self._config
    flags = self._browser_options["args"]
    if config.extra_flags or extra_flags:
        flags = list(set(tuple(flags) + tuple(extra_flags or ()) + tuple(config.extra_flags or ())))
    if config.dns_over_https:
        flags = list(flags) + ["--dns-over-https-templates=https://cloudflare-dns.com/dns-query"]
    if config.locale:
        base_lang = config.locale.split("-")[0].lower()
        accept_lang = f"{config.locale},{base_lang}" if base_lang != config.locale.lower() else config.locale
        flags = list(flags) + [f"--lang={config.locale}", f"--accept-lang={accept_lang}"]
    self._browser_options.update(
        {"args": flags, "headless": config.headless, "channel": "chrome" if config.real_chrome else "chromium"}
    )
    if config.executable_path:
        self._browser_options["executable_path"] = config.executable_path
    self._user_data_dir = config.user_data_dir

__validate__

__validate__(**params)
源代码位于 scrapling/engines/_browsers/_base.py
def __validate__(self, **params):
    self._config = self.__validate_routine__(params, model=self._config_class)
    self._context_options.update(
        {
            "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"],
        }
    )
    self.__generate_stealth_options()

save_state async

save_state(path)

将 Cookie、本地存储和 IndexedDB 保存到与 Playwright 兼容的 JSON 文件。

需要已启动且未启用代理轮换的会话。不保存 sessionStorage。

源代码位于 scrapling/engines/_browsers/_base.py
async def save_state(self, path: str | Path) -> None:
    """Save cookies, local storage and IndexedDB to a Playwright-compatible JSON file.

    Requires a started session without proxy rotation. Does not save sessionStorage.
    """
    if not self._is_alive or self.context is None:
        raise RuntimeError("Session state requires a started browser session without proxy rotation")
    await self.context.storage_state(path=Path(path), indexed_db=True)

load_state async

load_state(path)

使用与 Playwright 兼容的 JSON 文件替换 Cookie、本地存储和 IndexedDB。

需要已启动且未启用代理轮换的会话。获取或重新加载页面后,才能使用恢复的登录状态。

源代码位于 scrapling/engines/_browsers/_base.py
async def load_state(self, path: str | Path) -> None:
    """Replace cookies, local storage and IndexedDB from a Playwright-compatible JSON file.

    Requires a started session without proxy rotation. Fetch or reload pages to use the restored login.
    """
    if not self._is_alive or self.context is None:
        raise RuntimeError("Session state requires a started browser session without proxy rotation")
    await self.context.set_storage_state(path)

close_pages async

close_pages()

关闭会话池中的所有标签页。下一次请求会打开新的标签页。

源代码位于 scrapling/engines/_browsers/_base.py
async def close_pages(self) -> None:
    """Close every open tab in the session's pool. The next request opens a fresh tab."""
    for page_info in self.page_pool.clear():
        with suppress(Exception):
            await cast(AsyncPage, page_info.page).close()

close async

close()

关闭所有资源。

源代码位于 scrapling/engines/_browsers/_base.py
async def close(self):
    """Close all resources"""
    self.network._detach()
    if not self._is_alive:  # pragma: no cover
        return

    await self.close_pages()
    try:
        if self.context and self._owns_context:
            await self.context.close()
    finally:
        self.context = None
        try:
            if self.browser:
                await self.browser.close()
        finally:
            self.browser = None
            try:
                if self.playwright:
                    await self.playwright.stop()
            finally:
                self.playwright = None
                self._is_alive = False

__aenter__ async

__aenter__()
源代码位于 scrapling/engines/_browsers/_base.py
async def __aenter__(self):
    await self.start()
    return self

__aexit__ async

__aexit__(exc_type, exc_val, exc_tb)
源代码位于 scrapling/engines/_browsers/_base.py
async def __aexit__(self, exc_type, exc_val, exc_tb):
    await self.close()

get_pool_stats

get_pool_stats()

获取当前页面池的统计信息。

源代码位于 scrapling/engines/_browsers/_base.py
def get_pool_stats(self) -> Dict[str, int]:
    """Get statistics about the current page pool"""
    return {
        "total_pages": self.page_pool.pages_count,
        "busy_pages": self.page_pool.busy_count,
        "max_pages": self.max_pages,
    }

start async

start()

为此实例及上下文创建浏览器。

源代码位于 scrapling/engines/_browsers/_stealth.py
async def start(self) -> None:
    """Create a browser for this instance and context."""
    if not self.playwright:
        self.playwright = await async_playwright().start()
        self._is_alive = True
        try:
            await self._create_context()
            if self.context:
                self.context = await self._initialize_context(self._config, self.context)
        except BaseException:
            with suppress(Exception):
                await self.close()
            raise
    else:
        raise RuntimeError("Session has been already started")

fetch async

fetch(url, **kwargs)

打开浏览器,按所选选项发送请求。

参数 说明
url

目标 URL。

类型: str

google_search

默认开启,Scrapling 会设置 Google referer 请求头。

timeout

页面所有操作和等待的超时时间,单位为毫秒,默认为 30,000。

wait

所有步骤完成后,在关闭页面并返回 Response 对象前额外等待的时间,单位为毫秒。

page_action

用于自动化的函数,接收 page 对象,在导航后执行所需操作。

page_setup

接收 page 对象并在导航前执行的函数。用于注册必须在页面加载前准备好的事件监听器或路由。

extra_headers

要添加到请求中的额外请求头字典。同时使用时,google_search 设置的 referer 优先于这里的值。

disable_resources

阻止不必要的资源请求以提高速度。类型包括 font、image、media、beacon、object、imageset、texttrack、websocket、csp_report 和 stylesheet。

blocked_domains

要阻止请求的域名集合,也会匹配子域名。例如,"example.com" 也会阻止 "sub.example.com"。

wait_selector

等待指定 CSS 选择器达到指定状态。

wait_selector_state

等待 wait_selector 指定的元素达到这个状态。默认为 attached。

network_idle

等待页面至少连续 500 ms 没有网络连接。

load_dom

等待页面上的所有 JavaScript 加载并执行,默认开启。

pierce_shadow

将开放的 Shadow DOM 内容加入响应 HTML,默认为 False。

solve_cloudflare

返回响应前,处理所有类型的 Cloudflare Turnstile 和 Interstitial 挑战。

selector_config

创建最终 Selector 对象时传入的参数。

proxy

覆盖代理轮换器和会话代理的固定代理。会为它创建并使用新的浏览器上下文。

返回 说明
Response

一个 Response 对象。

源代码位于 scrapling/engines/_browsers/_stealth.py
async def fetch(self, url: str, **kwargs: Unpack[StealthFetchParams]) -> Response:
    """Opens up the browser and do your request based on your chosen options.

    :param url: The Target url.
    :param google_search: Enabled by default, Scrapling will set a Google referer header.
    :param timeout: The timeout in milliseconds that is used in all operations and waits through the page. The default is 30,000
    :param wait: The time (milliseconds) the fetcher will wait after everything finishes before closing the page and returning the ` Response ` object.
    :param page_action: Added for automation. A function that takes the `page` object, runs after navigation, and does the automation you need.
    :param page_setup: A function that takes the `page` object, runs before navigation. Use it to register event listeners or routes that must be set up before the page loads.
    :param extra_headers: A dictionary of extra headers to add to the request. _The referer set by `google_search` takes priority over the referer set here if used together._
    :param disable_resources: Drop requests for unnecessary resources for a speed boost.
        Requests dropped are of type `font`, `image`, `media`, `beacon`, `object`, `imageset`, `texttrack`, `websocket`, `csp_report`, and `stylesheet`.
    :param blocked_domains: A set of domain names to block requests to. Subdomains are also matched (e.g., ``"example.com"`` blocks ``"sub.example.com"`` too).
    :param wait_selector: Wait for a specific CSS selector to be in a specific state.
    :param wait_selector_state: The state to wait for the selector given with `wait_selector`. The default state is `attached`.
    :param network_idle: Wait for the page until there are no network connections for at least 500 ms.
    :param load_dom: Enabled by default, wait for all JavaScript on page(s) to fully load and execute.
    :param pierce_shadow: Include open Shadow DOM content in the response HTML. Defaults to False.
    :param solve_cloudflare: Solves all types of the Cloudflare's Turnstile/Interstitial challenges before returning the response to you.
    :param selector_config: The arguments that will be passed in the end while creating the final Selector's class.
    :param proxy: Static proxy to override rotator and session proxy. A new browser context will be created and used with it.
    :return: A `Response` object.
    """
    static_proxy = kwargs.pop("proxy", None)
    if not self._owns_context:
        static_proxy = None

    params = _validate(kwargs, self, StealthConfig)

    if not self._is_alive:  # pragma: no cover
        raise RuntimeError("Context manager has been closed")

    request_headers_keys = {h.lower() for h in params.extra_headers.keys()} if params.extra_headers else set()
    referer = (
        "https://www.google.com/" if (params.google_search and "referer" not in request_headers_keys) else None
    )

    for attempt in range(self._config.retries):
        proxy: Optional[ProxyType] = None
        if self._config.proxy_rotator and static_proxy is None:
            proxy = self._config.proxy_rotator.get_proxy()
        else:
            proxy = static_proxy

        async with self._page_generator(
            params.timeout, params.extra_headers, params.disable_resources, proxy, params.blocked_domains
        ) as page_info:
            final_response: List = [None]
            page = page_info.page
            handler = self._create_response_handler(page_info, final_response)
            page.on("response", handler)
            try:
                if params.page_setup:
                    try:
                        await params.page_setup(page)
                    except Exception as e:  # pragma: no cover
                        log.error(f"Error executing page_setup: {e}")

                try:
                    first_response = await page.goto(url, referer=referer)
                    await self._wait_for_page_stability(page, params.load_dom, params.network_idle)

                    if not first_response:
                        raise RuntimeError(f"Failed to get response for {url}")

                    if params.solve_cloudflare:
                        await self._cloudflare_solver(page)
                        # Make sure the page is fully loaded after the captcha
                        await self._wait_for_page_stability(page, params.load_dom, params.network_idle)

                    if params.page_action:
                        try:
                            _ = await params.page_action(page)
                        except Exception as e:  # pragma: no cover
                            log.error(f"Error executing page_action: {e}")

                    if params.wait_selector:
                        try:
                            waiter: AsyncLocator = page.locator(params.wait_selector)
                            await waiter.first.wait_for(state=params.wait_selector_state)
                            await self._wait_for_page_stability(page, params.load_dom, params.network_idle)
                        except Exception as e:  # pragma: no cover
                            log.error(f"Error waiting for selector {params.wait_selector}: {e}")

                    await page.wait_for_timeout(params.wait)

                    response = await ResponseFactory.from_async_playwright_response(
                        page,
                        first_response,
                        final_response[0],
                        params.selector_config,
                        meta={"proxy": proxy},
                        pierce_shadow=params.pierce_shadow,
                    )
                    return response

                except Exception as e:
                    page_info.mark_error()
                    if attempt < self._config.retries - 1:
                        if is_proxy_error(e):
                            log.warning(
                                f"Proxy '{proxy}' failed (attempt {attempt + 1}) | Retrying in {self._config.retry_delay}s..."
                            )
                        else:
                            log.warning(
                                f"Attempt {attempt + 1} failed: {e}. Retrying in {self._config.retry_delay}s..."
                            )
                        await asyncio_sleep(self._config.retry_delay)
                    else:
                        log.error(f"Failed after {self._config.retries} attempts: {e}")
                        raise
            finally:
                page.remove_listener("response", handler)

    raise RuntimeError("Request failed")  # pragma: no cover

远程会话

scrapling.fetchers.RemoteSession

RemoteSession(cdp_url, *, new_context=True, **kwargs)

基类: _RemoteSessionMixin, StealthySession


              flowchart TD
              scrapling.fetchers.RemoteSession[RemoteSession]
              scrapling.engines._browsers._remote._RemoteSessionMixin[_RemoteSessionMixin]
              scrapling.engines._browsers._stealth.StealthySession[StealthySession]
              scrapling.engines._browsers._base.SyncSession[SyncSession]
              scrapling.engines._browsers._base.StealthySessionMixin[StealthySessionMixin]
              scrapling.engines._browsers._base.BaseSessionMixin[BaseSessionMixin]

                              scrapling.engines._browsers._remote._RemoteSessionMixin --> scrapling.fetchers.RemoteSession
                                scrapling.engines._browsers._base.StealthySessionMixin --> scrapling.engines._browsers._remote._RemoteSessionMixin
                                scrapling.engines._browsers._base.BaseSessionMixin --> scrapling.engines._browsers._base.StealthySessionMixin
                


                scrapling.engines._browsers._stealth.StealthySession --> scrapling.fetchers.RemoteSession
                                scrapling.engines._browsers._base.SyncSession --> scrapling.engines._browsers._stealth.StealthySession
                
                scrapling.engines._browsers._base.StealthySessionMixin --> scrapling.engines._browsers._stealth.StealthySession
                                scrapling.engines._browsers._base.BaseSessionMixin --> scrapling.engines._browsers._base.StealthySessionMixin
                




              click scrapling.fetchers.RemoteSession href "" "scrapling.fetchers.RemoteSession"
              click scrapling.engines._browsers._remote._RemoteSessionMixin href "" "scrapling.engines._browsers._remote._RemoteSessionMixin"
              click scrapling.engines._browsers._stealth.StealthySession href "" "scrapling.engines._browsers._stealth.StealthySession"
              click scrapling.engines._browsers._base.SyncSession href "" "scrapling.engines._browsers._base.SyncSession"
              click scrapling.engines._browsers._base.StealthySessionMixin href "" "scrapling.engines._browsers._base.StealthySessionMixin"
              click scrapling.engines._browsers._base.BaseSessionMixin href "" "scrapling.engines._browsers._base.BaseSessionMixin"
            

A CDP browser session that creates its own context or borrows the default context.

使用页面池的浏览器会话管理器。默认使用持久浏览器上下文和临时用户配置目录。

参数 说明
record_requests

保存已完成的浏览器请求和响应。失败或尚未完成的请求会被省略,默认为 False。

max_recorded_requests

每个会话最多保留的请求数,默认为 1,000,旧条目会被移除。

headless

以无头模式运行,不显示窗口,这是默认设置;也可以显示浏览器窗口。

disable_resources

阻止不必要的资源请求以提高速度。类型包括 font、image、media、beacon、object、imageset、texttrack、websocket、csp_report 和 stylesheet。

blocked_domains

要阻止请求的域名集合,也会匹配子域名。例如,"example.com" 也会阻止 "sub.example.com"。

useragent

指定 User-Agent 字符串。未指定时,Fetcher 会生成并使用相同浏览器的真实 User-Agent。

cookies

为下一次请求设置 Cookie。

network_idle

等待页面至少连续 500 ms 没有网络连接。

timeout

页面所有操作和等待的超时时间,单位为毫秒,默认为 30,000。

wait

所有步骤完成后,在关闭页面并返回 Response 对象前额外等待的时间,单位为毫秒。

page_action

用于自动化的函数,接收 page 对象,在导航后执行所需操作。

page_setup

接收 page 对象并在导航前执行的函数。用于注册必须在页面加载前准备好的事件监听器或路由。

wait_selector

等待指定 CSS 选择器达到指定状态。

init_script

JavaScript 文件的绝对路径,在此会话中的每个页面创建时执行。

locale

区域设置,例如 en-GB、de-DE。影响 navigator.language、请求头 Accept-Language,以及数字和日期格式。默认使用系统区域设置。

timezone_id

修改浏览器时区,默认使用系统时区。

wait_selector_state

等待 wait_selector 指定的元素达到这个状态。默认为 attached。

solve_cloudflare

返回响应前,处理所有类型的 Cloudflare Turnstile 和 Interstitial 挑战。

real_chrome

如果设备上已安装 Chrome,启用此选项后,Fetcher 会启动并使用它。

hide_canvas

为 Canvas 操作添加随机噪声,防止指纹识别。

block_webrtc

强制 WebRTC 遵守代理设置,避免泄露本地 IP 地址。

allow_webgl

默认开启。关闭后会完全禁用 WebGL 和 WebGL 2.0。不建议关闭,因为很多 WAF 会检查 WebGL 是否启用。

load_dom

等待页面上的所有 JavaScript 加载并执行,默认开启。

pierce_shadow

将开放的 Shadow DOM 内容加入响应 HTML,默认为 False。

google_search

默认开启,Scrapling 会设置 Google referer 请求头。

extra_headers

要添加到请求中的额外请求头字典。同时使用时,google_search 设置的 referer 优先于这里的值。

proxy

请求使用的代理,可以是字符串,或仅包含 'server'、'username'、'password' 的字典。

user_data_dir

用户数据目录的路径,用于保存 Cookie、本地存储等浏览器会话数据。默认创建临时目录。

extra_flags

启动浏览器时传入的额外参数列表。

selector_config

创建最终 Selector 对象时传入的参数。

additional_args

传给 Playwright 上下文的额外设置,优先级高于 Scrapling 设置。

Connect to a remote browser when the session starts.

cdp_url

HTTP or WebSocket CDP endpoint of an existing Chromium browser.

类型: str

new_context

Create and close a separate context. If False, keep the existing default context open and ignore useragent, locale, timezone_id, proxy, proxy_rotator and additional_args.

类型: bool 默认值: True

kwargs

Shared session and page options. Browser launch options do not apply. Cookies and init scripts affect the shared context when new_context is False.

类型: Unpack[RemoteSessionParams] 默认值: {}

源代码位于 scrapling/engines/_browsers/_remote.py
def __init__(self, cdp_url: str, *, new_context: bool = True, **kwargs: Unpack[RemoteSessionParams]):
    """Connect to a remote browser when the session starts.

    :param cdp_url: HTTP or WebSocket CDP endpoint of an existing Chromium browser.
    :param new_context: Create and close a separate context. If False, keep the existing default context open
        and ignore useragent, locale, timezone_id, proxy, proxy_rotator and additional_args.
    :param kwargs: Shared session and page options. Browser launch options do not apply.
        Cookies and init scripts affect the shared context when new_context is False.
    """
    params: Dict[str, Any] = dict(kwargs, cdp_url=cdp_url, new_context=new_context)
    super().__init__(**params)
    self._owns_context = self._config.new_context

max_pages instance-attribute

max_pages = max_pages

network instance-attribute

network = NetworkRecorder(
    enabled=record_requests,
    max_requests=max_recorded_requests,
)

page_pool instance-attribute

page_pool = PagePool(max_pages)

playwright instance-attribute

playwright = None

context instance-attribute

context = None

browser instance-attribute

browser = None

__slots__ class-attribute instance-attribute

__slots__ = (
    "_config",
    "_context_options",
    "_browser_options",
    "_user_data_dir",
    "_headers_keys",
    "max_pages",
    "page_pool",
    "_max_wait_for_page",
    "playwright",
    "context",
)

__validate_routine__

__validate_routine__(params, model)
源代码位于 scrapling/engines/_browsers/_base.py
def __validate_routine__(
    self, params: Dict, model: type[PlaywrightConfig] | type[StealthConfig]
) -> PlaywrightConfig | StealthConfig:
    # Dark color scheme bypasses the 'prefersLightColor' check in creepjs
    self._context_options: Dict[str, Any] = {"color_scheme": "dark", "device_scale_factor": 2}
    self._browser_options: Dict[str, Any] = {
        "args": DEFAULT_ARGS,
        "ignore_default_args": HARMFUL_ARGS,
    }
    if "__max_pages" in params:
        params["max_pages"] = params.pop("__max_pages")

    config = validate(params, model=model)
    self._headers_keys = (
        {header.lower() for header in config.extra_headers.keys()} if config.extra_headers else set()
    )

    return config

__generate_context_options__

__generate_context_options__()
源代码位于 scrapling/engines/_browsers/_base.py
def __generate_context_options__(self) -> None:
    config: PlaywrightConfig | StealthConfig = self._config
    self._context_options.update(
        {
            "proxy": config.proxy,
            "timezone_id": config.timezone_id,
            "extra_http_headers": config.extra_headers,
        }
    )
    # The default useragent in the headful is always correct now in the current versions of Playwright
    if config.useragent:
        self._context_options["user_agent"] = config.useragent
    elif not config.useragent and config.headless:
        self._context_options["user_agent"] = (
            __default_chrome_useragent__ if config.real_chrome else __default_useragent__
        )

    if config.additional_args:
        self._context_options.update(config.additional_args)

__generate_options__

__generate_options__(extra_flags=None)
源代码位于 scrapling/engines/_browsers/_remote.py
def __generate_options__(self, extra_flags: Tuple | None = None) -> None:
    self._browser_options = {}
    if self._config.new_context:
        if self._config.locale:
            self._context_options["locale"] = self._config.locale
        self.__generate_context_options__()
    else:
        self._context_options = {}

__validate__

__validate__(**params)
源代码位于 scrapling/engines/_browsers/_base.py
def __validate__(self, **params):
    self._config = self.__validate_routine__(params, model=self._config_class)
    self._context_options.update(
        {
            "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"],
        }
    )
    self.__generate_stealth_options()

start

start()

为此实例及上下文创建浏览器。

源代码位于 scrapling/engines/_browsers/_stealth.py
def start(self) -> None:
    """Create a browser for this instance and context."""
    if not self.playwright:
        self.playwright = sync_playwright().start()
        self._is_alive = True
        try:
            self._create_context()
            if self.context:
                self.context = self._initialize_context(self._config, self.context)
        except BaseException:
            with suppress(Exception):
                self.close()
            raise
    else:
        raise RuntimeError("Session has been already started")

save_state

save_state(path)

将 Cookie、本地存储和 IndexedDB 保存到与 Playwright 兼容的 JSON 文件。

需要已启动且未启用代理轮换的会话。不保存 sessionStorage。

源代码位于 scrapling/engines/_browsers/_base.py
def save_state(self, path: str | Path) -> None:
    """Save cookies, local storage and IndexedDB to a Playwright-compatible JSON file.

    Requires a started session without proxy rotation. Does not save sessionStorage.
    """
    if not self._is_alive or self.context is None:
        raise RuntimeError("Session state requires a started browser session without proxy rotation")
    self.context.storage_state(path=Path(path), indexed_db=True)

load_state

load_state(path)

使用与 Playwright 兼容的 JSON 文件替换 Cookie、本地存储和 IndexedDB。

需要已启动且未启用代理轮换的会话。获取或重新加载页面后,才能使用恢复的登录状态。

源代码位于 scrapling/engines/_browsers/_base.py
def load_state(self, path: str | Path) -> None:
    """Replace cookies, local storage and IndexedDB from a Playwright-compatible JSON file.

    Requires a started session without proxy rotation. Fetch or reload pages to use the restored login.
    """
    if not self._is_alive or self.context is None:
        raise RuntimeError("Session state requires a started browser session without proxy rotation")
    self.context.set_storage_state(path)

close_pages

close_pages()

关闭会话池中的所有标签页。下一次请求会打开新的标签页。

源代码位于 scrapling/engines/_browsers/_base.py
def close_pages(self) -> None:
    """Close every open tab in the session's pool. The next request opens a fresh tab."""
    for page_info in self.page_pool.clear():
        with suppress(Exception):
            page_info.page.close()

close

close()

关闭所有资源。

源代码位于 scrapling/engines/_browsers/_base.py
def close(self):  # pragma: no cover
    """Close all resources"""
    self.network._detach()
    if not self._is_alive:
        return

    self.close_pages()
    try:
        if self.context and self._owns_context:
            self.context.close()
    finally:
        self.context = None
        try:
            if self.browser:
                self.browser.close()
        finally:
            self.browser = None
            try:
                if self.playwright:
                    self.playwright.stop()
            finally:
                self.playwright = None
                self._is_alive = False

__enter__

__enter__()
源代码位于 scrapling/engines/_browsers/_base.py
def __enter__(self):
    self.start()
    return self

__exit__

__exit__(exc_type, exc_val, exc_tb)
源代码位于 scrapling/engines/_browsers/_base.py
def __exit__(self, exc_type, exc_val, exc_tb):
    self.close()

get_pool_stats

get_pool_stats()

获取当前页面池的统计信息。

源代码位于 scrapling/engines/_browsers/_base.py
def get_pool_stats(self) -> Dict[str, int]:
    """Get statistics about the current page pool"""
    return {
        "total_pages": self.page_pool.pages_count,
        "busy_pages": self.page_pool.busy_count,
        "max_pages": self.max_pages,
    }

fetch

fetch(url, **kwargs)

打开浏览器,按所选选项发送请求。

参数 说明
url

目标 URL。

类型: str

google_search

默认开启,Scrapling 会设置 Google referer 请求头。

timeout

页面所有操作和等待的超时时间,单位为毫秒,默认为 30,000。

wait

所有步骤完成后,在关闭页面并返回 Response 对象前额外等待的时间,单位为毫秒。

page_action

用于自动化的函数,接收 page 对象,在导航后执行所需操作。

page_setup

接收 page 对象并在导航前执行的函数。用于注册必须在页面加载前准备好的事件监听器或路由。

extra_headers

要添加到请求中的额外请求头字典。同时使用时,google_search 设置的 referer 优先于这里的值。

disable_resources

阻止不必要的资源请求以提高速度。类型包括 font、image、media、beacon、object、imageset、texttrack、websocket、csp_report 和 stylesheet。

blocked_domains

要阻止请求的域名集合,也会匹配子域名。例如,"example.com" 也会阻止 "sub.example.com"。

wait_selector

等待指定 CSS 选择器达到指定状态。

wait_selector_state

等待 wait_selector 指定的元素达到这个状态。默认为 attached。

network_idle

等待页面至少连续 500 ms 没有网络连接。

load_dom

等待页面上的所有 JavaScript 加载并执行,默认开启。

pierce_shadow

将开放的 Shadow DOM 内容加入响应 HTML,默认为 False。

solve_cloudflare

返回响应前,处理所有类型的 Cloudflare Turnstile 和 Interstitial 挑战。

selector_config

创建最终 Selector 对象时传入的参数。

proxy

覆盖代理轮换器和会话代理的固定代理。会为它创建并使用新的浏览器上下文。

返回 说明
Response

一个 Response 对象。

源代码位于 scrapling/engines/_browsers/_stealth.py
def fetch(self, url: str, **kwargs: Unpack[StealthFetchParams]) -> Response:
    """Opens up the browser and do your request based on your chosen options.

    :param url: The Target url.
    :param google_search: Enabled by default, Scrapling will set a Google referer header.
    :param timeout: The timeout in milliseconds that is used in all operations and waits through the page. The default is 30,000
    :param wait: The time (milliseconds) the fetcher will wait after everything finishes before closing the page and returning the ` Response ` object.
    :param page_action: Added for automation. A function that takes the `page` object, runs after navigation, and does the automation you need.
    :param page_setup: A function that takes the `page` object, runs before navigation. Use it to register event listeners or routes that must be set up before the page loads.
    :param extra_headers: A dictionary of extra headers to add to the request. _The referer set by `google_search` takes priority over the referer set here if used together._
    :param disable_resources: Drop requests for unnecessary resources for a speed boost.
        Requests dropped are of type `font`, `image`, `media`, `beacon`, `object`, `imageset`, `texttrack`, `websocket`, `csp_report`, and `stylesheet`.
    :param blocked_domains: A set of domain names to block requests to. Subdomains are also matched (e.g., ``"example.com"`` blocks ``"sub.example.com"`` too).
    :param wait_selector: Wait for a specific CSS selector to be in a specific state.
    :param wait_selector_state: The state to wait for the selector given with `wait_selector`. The default state is `attached`.
    :param network_idle: Wait for the page until there are no network connections for at least 500 ms.
    :param load_dom: Enabled by default, wait for all JavaScript on page(s) to fully load and execute.
    :param pierce_shadow: Include open Shadow DOM content in the response HTML. Defaults to False.
    :param solve_cloudflare: Solves all types of the Cloudflare's Turnstile/Interstitial challenges before returning the response to you.
    :param selector_config: The arguments that will be passed in the end while creating the final Selector's class.
    :param proxy: Static proxy to override rotator and session proxy. A new browser context will be created and used with it.
    :return: A `Response` object.
    """
    static_proxy = kwargs.pop("proxy", None)
    if not self._owns_context:
        static_proxy = None

    params = _validate(kwargs, self, StealthConfig)
    if not self._is_alive:  # pragma: no cover
        raise RuntimeError("Context manager has been closed")

    request_headers_keys = {h.lower() for h in params.extra_headers.keys()} if params.extra_headers else set()
    referer = (
        "https://www.google.com/" if (params.google_search and "referer" not in request_headers_keys) else None
    )

    for attempt in range(self._config.retries):
        proxy: Optional[ProxyType] = None
        if self._config.proxy_rotator and static_proxy is None:
            proxy = self._config.proxy_rotator.get_proxy()
        else:
            proxy = static_proxy

        with self._page_generator(
            params.timeout, params.extra_headers, params.disable_resources, proxy, params.blocked_domains
        ) as page_info:
            final_response: List = [None]
            page = page_info.page
            handler = self._create_response_handler(page_info, final_response)
            page.on("response", handler)
            try:
                if params.page_setup:
                    try:
                        params.page_setup(page)
                    except Exception as e:  # pragma: no cover
                        log.error(f"Error executing page_setup: {e}")

                try:
                    first_response = page.goto(url, referer=referer)
                    self._wait_for_page_stability(page, params.load_dom, params.network_idle)

                    if not first_response:
                        raise RuntimeError(f"Failed to get response for {url}")

                    if params.solve_cloudflare:
                        self._cloudflare_solver(page)
                        # Make sure the page is fully loaded after the captcha
                        self._wait_for_page_stability(page, params.load_dom, params.network_idle)

                    if params.page_action:
                        try:
                            _ = params.page_action(page)
                        except Exception as e:  # pragma: no cover
                            log.error(f"Error executing page_action: {e}")

                    if params.wait_selector:
                        try:
                            waiter: Locator = page.locator(params.wait_selector)
                            waiter.first.wait_for(state=params.wait_selector_state)
                            self._wait_for_page_stability(page, params.load_dom, params.network_idle)
                        except Exception as e:  # pragma: no cover
                            log.error(f"Error waiting for selector {params.wait_selector}: {e}")

                    page.wait_for_timeout(params.wait)

                    response = ResponseFactory.from_playwright_response(
                        page,
                        first_response,
                        final_response[0],
                        params.selector_config,
                        meta={"proxy": proxy},
                        pierce_shadow=params.pierce_shadow,
                    )
                    return response

                except Exception as e:
                    page_info.mark_error()
                    if attempt < self._config.retries - 1:
                        if is_proxy_error(e):
                            log.warning(
                                f"Proxy '{proxy}' failed (attempt {attempt + 1}) | Retrying in {self._config.retry_delay}s..."
                            )
                        else:
                            log.warning(
                                f"Attempt {attempt + 1} failed: {e}. Retrying in {self._config.retry_delay}s..."
                            )
                        time_sleep(self._config.retry_delay)
                    else:
                        log.error(f"Failed after {self._config.retries} attempts: {e}")
                        raise
            finally:
                page.remove_listener("response", handler)

    raise RuntimeError("Request failed")  # pragma: no cover

scrapling.fetchers.AsyncRemoteSession

AsyncRemoteSession(cdp_url, *, new_context=True, **kwargs)

基类: _RemoteSessionMixin, AsyncStealthySession


              flowchart TD
              scrapling.fetchers.AsyncRemoteSession[AsyncRemoteSession]
              scrapling.engines._browsers._remote._RemoteSessionMixin[_RemoteSessionMixin]
              scrapling.engines._browsers._stealth.AsyncStealthySession[AsyncStealthySession]
              scrapling.engines._browsers._base.AsyncSession[AsyncSession]
              scrapling.engines._browsers._base.StealthySessionMixin[StealthySessionMixin]
              scrapling.engines._browsers._base.BaseSessionMixin[BaseSessionMixin]

                              scrapling.engines._browsers._remote._RemoteSessionMixin --> scrapling.fetchers.AsyncRemoteSession
                                scrapling.engines._browsers._base.StealthySessionMixin --> scrapling.engines._browsers._remote._RemoteSessionMixin
                                scrapling.engines._browsers._base.BaseSessionMixin --> scrapling.engines._browsers._base.StealthySessionMixin
                


                scrapling.engines._browsers._stealth.AsyncStealthySession --> scrapling.fetchers.AsyncRemoteSession
                                scrapling.engines._browsers._base.AsyncSession --> scrapling.engines._browsers._stealth.AsyncStealthySession
                
                scrapling.engines._browsers._base.StealthySessionMixin --> scrapling.engines._browsers._stealth.AsyncStealthySession
                                scrapling.engines._browsers._base.BaseSessionMixin --> scrapling.engines._browsers._base.StealthySessionMixin
                




              click scrapling.fetchers.AsyncRemoteSession href "" "scrapling.fetchers.AsyncRemoteSession"
              click scrapling.engines._browsers._remote._RemoteSessionMixin href "" "scrapling.engines._browsers._remote._RemoteSessionMixin"
              click scrapling.engines._browsers._stealth.AsyncStealthySession href "" "scrapling.engines._browsers._stealth.AsyncStealthySession"
              click scrapling.engines._browsers._base.AsyncSession href "" "scrapling.engines._browsers._base.AsyncSession"
              click scrapling.engines._browsers._base.StealthySessionMixin href "" "scrapling.engines._browsers._base.StealthySessionMixin"
              click scrapling.engines._browsers._base.BaseSessionMixin href "" "scrapling.engines._browsers._base.BaseSessionMixin"
            

An async CDP session that creates its own context or borrows the default context.

使用页面池的浏览器会话管理器。默认使用持久浏览器上下文和临时用户配置目录。

参数 说明
record_requests

保存已完成的浏览器请求和响应。失败或尚未完成的请求会被省略,默认为 False。

max_recorded_requests

每个会话最多保留的请求数,默认为 1,000,旧条目会被移除。

headless

以无头模式运行,不显示窗口,这是默认设置;也可以显示浏览器窗口。

disable_resources

阻止不必要的资源请求以提高速度。类型包括 font、image、media、beacon、object、imageset、texttrack、websocket、csp_report 和 stylesheet。

blocked_domains

要阻止请求的域名集合,也会匹配子域名。例如,"example.com" 也会阻止 "sub.example.com"。

useragent

指定 User-Agent 字符串。未指定时,Fetcher 会生成并使用相同浏览器的真实 User-Agent。

cookies

为下一次请求设置 Cookie。

network_idle

等待页面至少连续 500 ms 没有网络连接。

timeout

页面所有操作和等待的超时时间,单位为毫秒,默认为 30,000。

wait

所有步骤完成后,在关闭页面并返回 Response 对象前额外等待的时间,单位为毫秒。

page_action

用于自动化的函数,接收 page 对象,在导航后执行所需操作。

page_setup

接收 page 对象并在导航前执行的函数。用于注册必须在页面加载前准备好的事件监听器或路由。

wait_selector

等待指定 CSS 选择器达到指定状态。

init_script

JavaScript 文件的绝对路径,在此会话中的每个页面创建时执行。

locale

区域设置,例如 en-GB、de-DE。影响 navigator.language、请求头 Accept-Language,以及数字和日期格式。默认使用系统区域设置。

timezone_id

修改浏览器时区,默认使用系统时区。

wait_selector_state

等待 wait_selector 指定的元素达到这个状态。默认为 attached。

solve_cloudflare

返回响应前,处理所有类型的 Cloudflare Turnstile 和 Interstitial 挑战。

real_chrome

如果设备上已安装 Chrome,启用此选项后,Fetcher 会启动并使用它。

hide_canvas

为 Canvas 操作添加随机噪声,防止指纹识别。

block_webrtc

强制 WebRTC 遵守代理设置,避免泄露本地 IP 地址。

allow_webgl

默认开启。关闭后会完全禁用 WebGL 和 WebGL 2.0。不建议关闭,因为很多 WAF 会检查 WebGL 是否启用。

load_dom

等待页面上的所有 JavaScript 加载并执行,默认开启。

pierce_shadow

将开放的 Shadow DOM 内容加入响应 HTML,默认为 False。

google_search

默认开启,Scrapling 会设置 Google referer 请求头。

extra_headers

要添加到请求中的额外请求头字典。同时使用时,google_search 设置的 referer 优先于这里的值。

proxy

请求使用的代理,可以是字符串,或仅包含 'server'、'username'、'password' 的字典。

user_data_dir

用户数据目录的路径,用于保存 Cookie、本地存储等浏览器会话数据。默认创建临时目录。

extra_flags

启动浏览器时传入的额外参数列表。

selector_config

创建最终 Selector 对象时传入的参数。

additional_args

传给 Playwright 上下文的额外设置,优先级高于 Scrapling 设置。

Connect to a remote browser when the session starts.

cdp_url

HTTP or WebSocket CDP endpoint of an existing Chromium browser.

类型: str

new_context

Create and close a separate context. If False, keep the existing default context open and ignore useragent, locale, timezone_id, proxy, proxy_rotator and additional_args.

类型: bool 默认值: True

kwargs

Shared session and page options. Browser launch options do not apply. Cookies and init scripts affect the shared context when new_context is False.

类型: Unpack[RemoteSessionParams] 默认值: {}

源代码位于 scrapling/engines/_browsers/_remote.py
def __init__(self, cdp_url: str, *, new_context: bool = True, **kwargs: Unpack[RemoteSessionParams]):
    """Connect to a remote browser when the session starts.

    :param cdp_url: HTTP or WebSocket CDP endpoint of an existing Chromium browser.
    :param new_context: Create and close a separate context. If False, keep the existing default context open
        and ignore useragent, locale, timezone_id, proxy, proxy_rotator and additional_args.
    :param kwargs: Shared session and page options. Browser launch options do not apply.
        Cookies and init scripts affect the shared context when new_context is False.
    """
    params: Dict[str, Any] = dict(kwargs, cdp_url=cdp_url, new_context=new_context)
    super().__init__(**params)
    self._owns_context = self._config.new_context

max_pages instance-attribute

max_pages = max_pages

network instance-attribute

network = NetworkRecorder(
    enabled=record_requests,
    max_requests=max_recorded_requests,
    asynchronous=True,
)

page_pool instance-attribute

page_pool = PagePool(max_pages)

playwright instance-attribute

playwright = None

context instance-attribute

context = None

browser instance-attribute

browser = None

__slots__ class-attribute instance-attribute

__slots__ = (
    "_config",
    "_context_options",
    "_browser_options",
    "_user_data_dir",
    "_headers_keys",
)

__validate_routine__

__validate_routine__(params, model)
源代码位于 scrapling/engines/_browsers/_base.py
def __validate_routine__(
    self, params: Dict, model: type[PlaywrightConfig] | type[StealthConfig]
) -> PlaywrightConfig | StealthConfig:
    # Dark color scheme bypasses the 'prefersLightColor' check in creepjs
    self._context_options: Dict[str, Any] = {"color_scheme": "dark", "device_scale_factor": 2}
    self._browser_options: Dict[str, Any] = {
        "args": DEFAULT_ARGS,
        "ignore_default_args": HARMFUL_ARGS,
    }
    if "__max_pages" in params:
        params["max_pages"] = params.pop("__max_pages")

    config = validate(params, model=model)
    self._headers_keys = (
        {header.lower() for header in config.extra_headers.keys()} if config.extra_headers else set()
    )

    return config

__generate_context_options__

__generate_context_options__()
源代码位于 scrapling/engines/_browsers/_base.py
def __generate_context_options__(self) -> None:
    config: PlaywrightConfig | StealthConfig = self._config
    self._context_options.update(
        {
            "proxy": config.proxy,
            "timezone_id": config.timezone_id,
            "extra_http_headers": config.extra_headers,
        }
    )
    # The default useragent in the headful is always correct now in the current versions of Playwright
    if config.useragent:
        self._context_options["user_agent"] = config.useragent
    elif not config.useragent and config.headless:
        self._context_options["user_agent"] = (
            __default_chrome_useragent__ if config.real_chrome else __default_useragent__
        )

    if config.additional_args:
        self._context_options.update(config.additional_args)

__generate_options__

__generate_options__(extra_flags=None)
源代码位于 scrapling/engines/_browsers/_remote.py
def __generate_options__(self, extra_flags: Tuple | None = None) -> None:
    self._browser_options = {}
    if self._config.new_context:
        if self._config.locale:
            self._context_options["locale"] = self._config.locale
        self.__generate_context_options__()
    else:
        self._context_options = {}

__validate__

__validate__(**params)
源代码位于 scrapling/engines/_browsers/_base.py
def __validate__(self, **params):
    self._config = self.__validate_routine__(params, model=self._config_class)
    self._context_options.update(
        {
            "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"],
        }
    )
    self.__generate_stealth_options()

start async

start()

为此实例及上下文创建浏览器。

源代码位于 scrapling/engines/_browsers/_stealth.py
async def start(self) -> None:
    """Create a browser for this instance and context."""
    if not self.playwright:
        self.playwright = await async_playwright().start()
        self._is_alive = True
        try:
            await self._create_context()
            if self.context:
                self.context = await self._initialize_context(self._config, self.context)
        except BaseException:
            with suppress(Exception):
                await self.close()
            raise
    else:
        raise RuntimeError("Session has been already started")

save_state async

save_state(path)

将 Cookie、本地存储和 IndexedDB 保存到与 Playwright 兼容的 JSON 文件。

需要已启动且未启用代理轮换的会话。不保存 sessionStorage。

源代码位于 scrapling/engines/_browsers/_base.py
async def save_state(self, path: str | Path) -> None:
    """Save cookies, local storage and IndexedDB to a Playwright-compatible JSON file.

    Requires a started session without proxy rotation. Does not save sessionStorage.
    """
    if not self._is_alive or self.context is None:
        raise RuntimeError("Session state requires a started browser session without proxy rotation")
    await self.context.storage_state(path=Path(path), indexed_db=True)

load_state async

load_state(path)

使用与 Playwright 兼容的 JSON 文件替换 Cookie、本地存储和 IndexedDB。

需要已启动且未启用代理轮换的会话。获取或重新加载页面后,才能使用恢复的登录状态。

源代码位于 scrapling/engines/_browsers/_base.py
async def load_state(self, path: str | Path) -> None:
    """Replace cookies, local storage and IndexedDB from a Playwright-compatible JSON file.

    Requires a started session without proxy rotation. Fetch or reload pages to use the restored login.
    """
    if not self._is_alive or self.context is None:
        raise RuntimeError("Session state requires a started browser session without proxy rotation")
    await self.context.set_storage_state(path)

close_pages async

close_pages()

关闭会话池中的所有标签页。下一次请求会打开新的标签页。

源代码位于 scrapling/engines/_browsers/_base.py
async def close_pages(self) -> None:
    """Close every open tab in the session's pool. The next request opens a fresh tab."""
    for page_info in self.page_pool.clear():
        with suppress(Exception):
            await cast(AsyncPage, page_info.page).close()

close async

close()

关闭所有资源。

源代码位于 scrapling/engines/_browsers/_base.py
async def close(self):
    """Close all resources"""
    self.network._detach()
    if not self._is_alive:  # pragma: no cover
        return

    await self.close_pages()
    try:
        if self.context and self._owns_context:
            await self.context.close()
    finally:
        self.context = None
        try:
            if self.browser:
                await self.browser.close()
        finally:
            self.browser = None
            try:
                if self.playwright:
                    await self.playwright.stop()
            finally:
                self.playwright = None
                self._is_alive = False

__aenter__ async

__aenter__()
源代码位于 scrapling/engines/_browsers/_base.py
async def __aenter__(self):
    await self.start()
    return self

__aexit__ async

__aexit__(exc_type, exc_val, exc_tb)
源代码位于 scrapling/engines/_browsers/_base.py
async def __aexit__(self, exc_type, exc_val, exc_tb):
    await self.close()

get_pool_stats

get_pool_stats()

获取当前页面池的统计信息。

源代码位于 scrapling/engines/_browsers/_base.py
def get_pool_stats(self) -> Dict[str, int]:
    """Get statistics about the current page pool"""
    return {
        "total_pages": self.page_pool.pages_count,
        "busy_pages": self.page_pool.busy_count,
        "max_pages": self.max_pages,
    }

fetch async

fetch(url, **kwargs)

打开浏览器,按所选选项发送请求。

参数 说明
url

目标 URL。

类型: str

google_search

默认开启,Scrapling 会设置 Google referer 请求头。

timeout

页面所有操作和等待的超时时间,单位为毫秒,默认为 30,000。

wait

所有步骤完成后,在关闭页面并返回 Response 对象前额外等待的时间,单位为毫秒。

page_action

用于自动化的函数,接收 page 对象,在导航后执行所需操作。

page_setup

接收 page 对象并在导航前执行的函数。用于注册必须在页面加载前准备好的事件监听器或路由。

extra_headers

要添加到请求中的额外请求头字典。同时使用时,google_search 设置的 referer 优先于这里的值。

disable_resources

阻止不必要的资源请求以提高速度。类型包括 font、image、media、beacon、object、imageset、texttrack、websocket、csp_report 和 stylesheet。

blocked_domains

要阻止请求的域名集合,也会匹配子域名。例如,"example.com" 也会阻止 "sub.example.com"。

wait_selector

等待指定 CSS 选择器达到指定状态。

wait_selector_state

等待 wait_selector 指定的元素达到这个状态。默认为 attached。

network_idle

等待页面至少连续 500 ms 没有网络连接。

load_dom

等待页面上的所有 JavaScript 加载并执行,默认开启。

pierce_shadow

将开放的 Shadow DOM 内容加入响应 HTML,默认为 False。

solve_cloudflare

返回响应前,处理所有类型的 Cloudflare Turnstile 和 Interstitial 挑战。

selector_config

创建最终 Selector 对象时传入的参数。

proxy

覆盖代理轮换器和会话代理的固定代理。会为它创建并使用新的浏览器上下文。

返回 说明
Response

一个 Response 对象。

源代码位于 scrapling/engines/_browsers/_stealth.py
async def fetch(self, url: str, **kwargs: Unpack[StealthFetchParams]) -> Response:
    """Opens up the browser and do your request based on your chosen options.

    :param url: The Target url.
    :param google_search: Enabled by default, Scrapling will set a Google referer header.
    :param timeout: The timeout in milliseconds that is used in all operations and waits through the page. The default is 30,000
    :param wait: The time (milliseconds) the fetcher will wait after everything finishes before closing the page and returning the ` Response ` object.
    :param page_action: Added for automation. A function that takes the `page` object, runs after navigation, and does the automation you need.
    :param page_setup: A function that takes the `page` object, runs before navigation. Use it to register event listeners or routes that must be set up before the page loads.
    :param extra_headers: A dictionary of extra headers to add to the request. _The referer set by `google_search` takes priority over the referer set here if used together._
    :param disable_resources: Drop requests for unnecessary resources for a speed boost.
        Requests dropped are of type `font`, `image`, `media`, `beacon`, `object`, `imageset`, `texttrack`, `websocket`, `csp_report`, and `stylesheet`.
    :param blocked_domains: A set of domain names to block requests to. Subdomains are also matched (e.g., ``"example.com"`` blocks ``"sub.example.com"`` too).
    :param wait_selector: Wait for a specific CSS selector to be in a specific state.
    :param wait_selector_state: The state to wait for the selector given with `wait_selector`. The default state is `attached`.
    :param network_idle: Wait for the page until there are no network connections for at least 500 ms.
    :param load_dom: Enabled by default, wait for all JavaScript on page(s) to fully load and execute.
    :param pierce_shadow: Include open Shadow DOM content in the response HTML. Defaults to False.
    :param solve_cloudflare: Solves all types of the Cloudflare's Turnstile/Interstitial challenges before returning the response to you.
    :param selector_config: The arguments that will be passed in the end while creating the final Selector's class.
    :param proxy: Static proxy to override rotator and session proxy. A new browser context will be created and used with it.
    :return: A `Response` object.
    """
    static_proxy = kwargs.pop("proxy", None)
    if not self._owns_context:
        static_proxy = None

    params = _validate(kwargs, self, StealthConfig)

    if not self._is_alive:  # pragma: no cover
        raise RuntimeError("Context manager has been closed")

    request_headers_keys = {h.lower() for h in params.extra_headers.keys()} if params.extra_headers else set()
    referer = (
        "https://www.google.com/" if (params.google_search and "referer" not in request_headers_keys) else None
    )

    for attempt in range(self._config.retries):
        proxy: Optional[ProxyType] = None
        if self._config.proxy_rotator and static_proxy is None:
            proxy = self._config.proxy_rotator.get_proxy()
        else:
            proxy = static_proxy

        async with self._page_generator(
            params.timeout, params.extra_headers, params.disable_resources, proxy, params.blocked_domains
        ) as page_info:
            final_response: List = [None]
            page = page_info.page
            handler = self._create_response_handler(page_info, final_response)
            page.on("response", handler)
            try:
                if params.page_setup:
                    try:
                        await params.page_setup(page)
                    except Exception as e:  # pragma: no cover
                        log.error(f"Error executing page_setup: {e}")

                try:
                    first_response = await page.goto(url, referer=referer)
                    await self._wait_for_page_stability(page, params.load_dom, params.network_idle)

                    if not first_response:
                        raise RuntimeError(f"Failed to get response for {url}")

                    if params.solve_cloudflare:
                        await self._cloudflare_solver(page)
                        # Make sure the page is fully loaded after the captcha
                        await self._wait_for_page_stability(page, params.load_dom, params.network_idle)

                    if params.page_action:
                        try:
                            _ = await params.page_action(page)
                        except Exception as e:  # pragma: no cover
                            log.error(f"Error executing page_action: {e}")

                    if params.wait_selector:
                        try:
                            waiter: AsyncLocator = page.locator(params.wait_selector)
                            await waiter.first.wait_for(state=params.wait_selector_state)
                            await self._wait_for_page_stability(page, params.load_dom, params.network_idle)
                        except Exception as e:  # pragma: no cover
                            log.error(f"Error waiting for selector {params.wait_selector}: {e}")

                    await page.wait_for_timeout(params.wait)

                    response = await ResponseFactory.from_async_playwright_response(
                        page,
                        first_response,
                        final_response[0],
                        params.selector_config,
                        meta={"proxy": proxy},
                        pierce_shadow=params.pierce_shadow,
                    )
                    return response

                except Exception as e:
                    page_info.mark_error()
                    if attempt < self._config.retries - 1:
                        if is_proxy_error(e):
                            log.warning(
                                f"Proxy '{proxy}' failed (attempt {attempt + 1}) | Retrying in {self._config.retry_delay}s..."
                            )
                        else:
                            log.warning(
                                f"Attempt {attempt + 1} failed: {e}. Retrying in {self._config.retry_delay}s..."
                            )
                        await asyncio_sleep(self._config.retry_delay)
                    else:
                        log.error(f"Failed after {self._config.retries} attempts: {e}")
                        raise
            finally:
                page.remove_listener("response", handler)

    raise RuntimeError("Request failed")  # pragma: no cover