首页
/ Scrapling StealthyFetcher 的 page_action 如何读取 init_script 写入的 window 全局变量

Scrapling StealthyFetcher 的 page_action 如何读取 init_script 写入的 window 全局变量

2026-09-08 16:27:01作者:霍妲思

在 Scrapling 中用 StealthyFetcher 抓取页面时,init_scriptpage_action 是两个常用参数:init_script 指向一个 JavaScript 文件,在页面创建时执行;page_action 是一个接收 Playwright page 对象的函数,在导航之后运行。一个常见的需求是:让 init_script 先把某些数据写到 window 全局变量上,再在 page_action 里把值读回来。StealthyFetcher 文档明确指出一个坑:Stealthy 模式默认使用 Patchright 的隔离执行上下文(isolated execution context),因此 page_action 想读到 init_script 写进 window 的变量,必须用 page.evaluate(..., isolated_context=False),不能直接读取。下面按这条路径给出完整写法。

init_script 与 page_action 的执行时机

先确认两个参数在请求流程中的位置,它们决定了你能在 page_action 里读到什么:

  • init_script 是注册到浏览器 context 上的(源码中通过 context 的 add_init_script(path=...) 实现,见 _base.py),所以它在页面创建时执行,对会话中的所有页面生效。文档对它的定义是:一个 JavaScript 文件的绝对路径
  • page_actionpage.goto() 导航完成、等待 load_dom/network_idle(若启用)之后立即执行,且早于 wait_selector 的等待;如果启用了 solve_cloudflare,它会先解决 Cloudflare 挑战再执行 page_action(执行顺序见 fetch 流程)。
  • 因此,导航完成后 page_action 运行时,init_script 早已执行完毕,window 上的变量已经存在——剩下的问题只是"在哪个执行上下文里读"。

单请求主路径:fetch 时同时传 init_script 和 page_action

准备一个 JavaScript 文件(内容自定,示例中的 myGlobalData 只是示例全局变量名,替换成你自己的 init 脚本实际写入的名字),保存后记住它的绝对路径。init_script 只接受绝对路径,相对路径不满足文档要求。

// init.js:init_script 指向的文件,示例内容
window.myGlobalData = {
    source: 'init-script',
    items: []
};

然后在 Python 侧传两个参数。page.evaluate 的第一个参数是要执行的 JS 表达式,即你在 init 脚本里写的全局变量名;isolated_context=False 是关键,它让表达式回到页面主世界执行,从而能拿到 init_script 写入的值:

from scrapling.fetchers import StealthyFetcher
from playwright.sync_api import Page

def read_init_global(page: Page):
    # 第一个参数为 JS 表达式,即 init.js 写入 window 的变量名
    value = page.evaluate('window.myGlobalData', isolated_context=False)
    print(value)  # 在 action 内打印确认读到的值,无固定预期输出

page = StealthyFetcher.fetch(
    'https://example.com',
    init_script='/absolute/path/to/init.js',  # 替换为你 init.js 的绝对路径
    page_action=read_init_global,
)

关于验证,文档没有给出固定成功日志,判断点在于执行上下文:按 StealthyFetcher 文档的说明init_script 注册在浏览器 context 上、于页面创建时运行;而 Stealthy 模式默认使用 Patchright 的隔离执行上下文,所以从 page_action 读取该 window 全局变量时必须isolated_context=False。如果读出来的不是你在 init 脚本里写入的值,先检查两点:init_script 是否用了绝对路径、page.evaluate 是否漏了 isolated_context=False

另一个需要注意的事实来自源码:page_action 抛出的异常会被 fetcher 捕获并记录为 Error executing page_action: ... 日志,而不会中断请求(见 _stealth.py)。所以不要依赖函数里抛异常来确认读取结果,应在 page_action 内把读到的值打印或记录下来,再据此判断。

异步版本

使用 async_fetch 时,传入的函数也必须是 async,page.evaluate 调用需要 await(文档在 DynamicFetcher 的 Browser Automation 一节说明了这一约定,StealthyFetcher 同为 Playwright 接口,规则一致):

from scrapling.fetchers import StealthyFetcher
from playwright.async_api import Page

async def read_init_global(page: Page):
    value = await page.evaluate('window.myGlobalData', isolated_context=False)
    print(value)

page = await StealthyFetcher.async_fetch(
    'https://example.com',
    init_script='/absolute/path/to/init.js',  # 替换为你 init.js 的绝对路径
    page_action=read_init_global,
)

可选分支:在 StealthySession 中配置

如果你要复用同一个浏览器发起多个请求,可以用 StealthySession。在会话类中,fetch 的全部参数都可以在构造会话时设置,但 init_script 不在文档列出的"可按单个请求覆盖"的参数列表里(该列表包含 page_actiontimeoutwait 等,见 文档说明),所以 init_script 应作为会话级配置传入,page_action 则可以在每次 session.fetch 时指定:

from scrapling.fetchers import StealthySession

def read_init_global(page: Page):
    value = page.evaluate('window.myGlobalData', isolated_context=False)
    print(value)

with StealthySession(
    init_script='/absolute/path/to/init.js'  # 会话级配置,对该会话所有页面生效
) as session:
    page = session.fetch('https://example.com', page_action=read_init_global)

限制与边界

  • init_script 必须是 JavaScript 文件的绝对路径,且作用于会话中的所有页面,不能按 URL 区分不同脚本。
  • isolated_context=False 是 Stealthy 模式下的必要处理,因为默认执行上下文是隔离的;文档没有为其他场景(如 DynamicFetcher)给出相同约定,本文不展开。
  • page_action 内部的异常只会被记录日志,请求仍会返回 Response 对象,排查时以日志中的 Error executing page_action: 为准。
  • page_action 执行时页面已完成 load_dom(默认启用)等待,此时 init_script 一定已经运行过;不需要为"脚本还没执行"额外加等待。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.74 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.81 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
595
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
920
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.63 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
518
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
389