Skip to main content

ruyiJS

基于 Firefox / SpiderMonkey 原生组件的 Python JavaScript 运行库。 在 Python 中执行 JavaScript,使用 DOM、Navigator、定时器和网络 API,无需启动浏览器窗口。

Python Platform

每个 Context 拥有独立进程和持续保存的 JavaScript 上下文;wheel 自带原生运行时,安装后可离线执行本地脚本。

from ruyijs import Context

with Context() as context:
    context.eval("let count = 40")
    print(context.eval("count += 2"))  # 42
    print(context.eval("navigator.userAgent"))

快速开始 · 常用功能 · 更多用法 · 运行示例

快速开始

当前版本 0.1.2,适用于 Windows 10 / 11 x64,需要 64 位 Python 3.10 或更高版本。已在 Python 3.14.6 下验证安装与运行。

python -m pip install ruyijs
python -c "import ruyijs; print(ruyijs.__version__)"

wheel 自带原生运行时,安装后运行本地脚本无需再次下载。

常用功能

功能 用法
JavaScript 执行 Context.eval(),同一上下文保留变量和函数
Python / JS 数据交换 set()、数组与对象转换、UNDEFINED
JS 函数调用 eval(..., to_py=False) 返回可调用的 JSFunction
Python 回调 expose() 将 Python 函数提供给 JavaScript
页面与 DOM load_page(url, html)、DOM 查询、经典脚本执行
环境配置 configure_fingerprint(),配置 Navigator、Screen、时区等
时间与调度 advance()、tick()、系统时钟与逻辑时钟
网络与代理 页面内 fetch / XHR,Context(proxy=...)
离线资源 put_resource() 提供脚本或请求响应
错误与日志 JSError、console_log()、net_log()

更多用法

传入数据、调用 JavaScript 函数

from ruyijs import Context

with Context() as context:
    context.set("config", {"offset": 2})
    add = context.eval("(value) => value + config.offset", to_py=False)
    print(add(40))  # 42

JSFunction / JSObject 引用随所属 Context 关闭而失效。需要普通 Python 数据时,可直接让 eval() 返回数组、对象或基本值。

调用 Python 函数

from ruyijs import Context

with Context() as context:
    context.expose(lambda a, b: a + b, "add")
    print(context.eval("add(20, 22)"))  # 42

回调中请使用传入的数据;同一个 Context 的嵌套调用会抛出 ReentrantError。

加载 HTML 与脚本

from ruyijs import Context

with Context() as context:
    context.put_resource("https://example.test/app.js", "window.answer = 42")
    context.load_page("https://example.test/", '''
        <script src="/app.js"></script><p id="message">hello</p>
    ''')
    print(context.eval("document.querySelector('#message').textContent"))  # hello
    print(context.eval("answer"))  # 42

load_page() 接收页面地址和 HTML 文本;相对资源地址按页面地址解析。上面的资源由 put_resource() 提供,整个示例可离线运行。

配置浏览器环境

from ruyijs import Context

with Context() as context:
    context.configure_fingerprint({
        "navigator": {"language": "zh-CN", "hardwareConcurrency": 8},
        "screen": {"width": 1920, "height": 1080},
        "viewport": {"width": 1280, "height": 720},
        "locale": {"timezone": "Asia/Shanghai"},
    })
    print(context.eval("[navigator.language, screen.width]"))  # ['zh-CN', 1920]

在首次执行页面脚本或加载 HTML 前提交配置。configure_fingerprint() 与 configure_environment() 使用同一套字段校验。

执行定时任务

from ruyijs import Context

with Context() as context:
    context.configure_clock("logical", epoch_ms=1700000000000)
    context.eval("globalThis.result = 0; setTimeout(() => { result = 42 }, 10)")
    context.advance(10)
    print(context.eval("result"))  # 42

定时器由宿主显式推进。逻辑时钟直接前进;默认系统时钟下,advance(10) 会实际等待相应时间。

使用 fetch 与代理

from time import monotonic
from ruyijs import Context

with Context(proxy="http://127.0.0.1:7890", timeout=30) as context:
    context.load_page("https://example.com/", "")
    context.eval('''
        globalThis.reply = null;
        fetch('/').then(async r => ({status: r.status, text: await r.text()}))
          .then(value => { reply = value })
          .catch(error => { reply = {error: String(error)} });
        undefined
    ''')
    deadline = monotonic() + 30
    while context.eval("reply") is None:
        if monotonic() >= deadline:
            raise TimeoutError("等待 fetch 超时")
        context.advance(25)
    print(context.eval("reply"))

将代理地址替换为实际使用的 HTTP(S) 代理;传入 proxy=None 使用直连。代理仅作用于当前上下文。页面请求需要网络连接,可用 net_log() 查看请求记录。

处理 JavaScript 错误

from ruyijs import Context, JSError

with Context(timeout=10) as context:
    try:
        context.eval("throw new TypeError('bad input')", filename="demo.js")
    except JSError as error:
        print(error.name, error.message)  # TypeError bad input
        print(error.stack)

timeout 限制启动及每次请求的等待时间;超时会关闭该上下文,后续工作需新建 Context。

运行示例

示例随包安装,无需下载仓库:

python -m ruyijs.examples                      # 列出全部示例及其安装路径
python -m ruyijs.examples google --query python --pages 1
python -m ruyijs.examples boss --query ai --city 101210100
python -m ruyijs.examples fangdi               # 网上房地产(瑞数 6)
python -m ruyijs.examples cebwm --pages 3      # 光大理财(瑞数定制)
python -m ruyijs.examples toutiao --pages 3    # 今日头条
python -m ruyijs.examples xhs --pages 3        # 小红书 rednote 推荐流
python -m ruyijs.examples geetest              # 极验一键通过
python -m ruyijs.examples yidun                # 网易易盾
python -m ruyijs.examples shumei               # 数美滑块
python -m ruyijs.examples tianyu               # 腾讯天御
python -m ruyijs.examples turnstile --direct --timeout 120  # ScrapingCourse Turnstile 实时网络登录闭环

示例均支持 --direct(直连)和 --proxy http://127.0.0.1:7890,在名称后加 --help 查看全部参数,--output result.json 可保存结果。各示例目录内附 README。线上结果受网络与站点当前响应影响。

使用范围与反馈

本版本提供 Windows x64 上的 JavaScript 执行及部分 Web API 环境,没有浏览器窗口和完整页面布局、渲染能力。

相关项目:ruyiHttp,基于 Firefox 原生网络组件的 Requests 风格 Python 请求库。

Metadata

Release files for ruyijs 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ruyijs 0.1.3
File Size Uploaded Provenance
ruyijs-0.1.3.tar.gz 89.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ruyijs 0.1.3
File Interpreter ABI Platform
ruyijs-0.1.3-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details

Total release size: 43.4 MB

Release files / ruyijs-0.1.3.tar.gz

Download URL ruyijs-0.1.3.tar.gz
Size 89.2 kB
Tags Source
SHA-256 checksum
How to use checksums
4bf2a386f6a6b1bf0315a5a125368891fce9ecf2a61ae024a5404caa6440defa
BLAKE2b-256 checksum
How to use checksums
30be586d127432603bf09d49dd267e5682060113b615ada1bee41657129fc6ab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / ruyijs-0.1.3-py3-none-win_amd64.whl

Download URL ruyijs-0.1.3-py3-none-win_amd64.whl
Size 43.4 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
2431fb75e282450a9b4963fa6fd0fc99607ca0d1eb054a43b5b653bee872d021
BLAKE2b-256 checksum
How to use checksums
aa828f563d9c236ca500bceb7a980598d9fc4b65bf08cf2df94f90dc2799d3fd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Security for ruyijs 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page