ruyiJS
基于 Firefox / SpiderMonkey 原生组件的 Python JavaScript 运行库。 在 Python 中执行 JavaScript,使用 DOM、Navigator、定时器和网络 API,无需启动浏览器窗口。
每个 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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ruyijs-0.1.3.tar.gz | 89.2 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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.