@ 浏览器无/ 功能: 在浏览器沙盒内任意运行 JavaScript .
见 函数节 我们的网站有更多信息.
安装
使用 npm :
npm install @browserless/function --save
关于
此软件包提供了 安全沙盒 用于运行任意 JavaScript 代码,可访问浏览器页面。 它在一个孤立的VM环境中执行用户提供的功能,可选择访问Puppeteer的页面API.
这个软件包做什么
这个 @browserless/function 软件包允许您 :
- 执行任意 JavaScript 在安全、孤立的VM沙盒里
- 访问浏览器页面 从沙盒内取出 用于 DOM 操作
- 抓取控制台输出 和执行概况数据
- 通过自定义数据 到运行时的沙盒函数
- 处理错误优雅 有结构化结果对象
使用量
首先,通过给工厂打电话来创建函数实例:
const createFunction = require('@browserless/function')()
你可以选择通过一个 tmpdir 用于沙盒工作目录 :
const createFunction = require('@browserless/function')({ tmpdir: '/tmp/functions' })
然后使用它来运行任意 JavaScript :
// Simple function without page access
const code = ({ query }) => query.value * 2
const myFn = createFunction(code)
const result = await myFn('https://example.com', { query: { value: 21 } })
console.log(result)
// => { isFulfilled: true, value: 42, profiling: {...}, logging: {...} }
访问页面
当您引用代码时 page,无浏览器自动提供访问 Puppeteer 页面:
const createFunction = require('@browserless/function')()
// Function with page access
const code = async ({ page }) => {
const title = await page.title()
const content = await page.evaluate(() => document.body.innerText)
return { title, content }
}
const scraper = createFunction(code)
const result = await scraper('https://example.com')
console.log(result)
// => { isFulfilled: true, value: { title: 'Example', content: '...' }, ... }
可用上下文
沙盒函数接收这些属性 :
| 财产 | 说明 |
|---|---|
url | 目标 URL 传递到函数( 不需要浏览器) |
page | 傀儡 页次 对象(如果在代码中引用) |
device | 设备描述符 userAgent 财务报告和审定财务报表 viewport |
...opts | 运行时通过的任何自定义选项 |
用于您函数的传递值 args。它们被保存在运行时间选项之外,所以一个名为 code, (中文(简体) ), source 或者说 vmOpts 到达您的函数而不是更改其运行方式 :
const myFn = createFunction(({ code }) => code, { args: { code: 'abc' } })
await myFn('https://example.com') // => { isFulfilled: true, value: 'abc', ... }
// per-call args merge over the ones given at creation
await myFn('https://example.com', { args: { code: 'xyz' } }) // value: 'xyz'
args 以相同名称赢得其他自定义选项. response 财务报告和审定财务报表 url 从运行时间来取胜 args也一样 page,当函数运行时;不使用的函数 page 还收到 args.page。 。 。 . device 从运行时间,和 args 不能设置它.
结果对象
该函数返回结构化结果 :
| 财产 | 说明 |
|---|---|
isFulfilled | true 如果执行成功, false 如果出错 |
value | 返回值(成功)或出错对象(失败) |
profiling | 执行时间和资源使用情况(见下文) |
logging | 抓取控制台输出( E)log, (中文(简体) ), warn, (中文(简体) ), error页:1 |
剖析
这个 profiling 对象包含相位时间和资源数据:
| 财产 | 说明 |
|---|---|
phases.compile | 编译沙盒脚本的时间( ms) |
phases.spawn | 产卵时间(毫秒) |
phases.run | 执行用户功能的时间( ms) |
phases.total | 壁点时间共计 |
cpu | CPU 消耗时间(毫秒) |
memory | 峰值内存使用量 (字节) |
减员
打电话 .teardown() 在工厂实例中清理沙盒资源:
const createFunction = require('@browserless/function')({ tmpdir: '/tmp/functions' })
// ... use createFunction ...
await createFunction.teardown()
扩展页
附加额外方法于 page. JSON 值成为了同步获取器. 函数作为协同方法内含( )this 是页面; 需要时使用函数而不是箭头 this) (中文(简体) ). 如果用户功能只使用这些方法,则 Chromium 不启动 :
const myFn = createFunction(({ page }) => page.html(), {
extendPage: { url, html }
})
const result = await myFn('https://example.com')
// => { isFulfilled: true, value: html, ... }
主机页面
附加方法于 page 表示主机在用户函数调用它们时决定,而不是在运行前决定的值. 工作功能从未达到任何成本 :
const myFn = createFunction(({ page }) => page.content(), {
hostPage: { content: () => fetchThePage(url) }
})
const result = await myFn('https://example.com')
// => { isFulfilled: true, value: html, ... }, and fetchThePage ran once
fetchThePage 运行, 因为函数等待 content返回函数 420 没有触摸 page 从来没有触发它, 也没有树枝它不采取:
const myFn = createFunction('async ({ page }) => (false ? await page.content() : "skipped")', {
hostPage: { content: () => fetchThePage(url) }
})
const result = await myFn('https://example.com')
// => { isFulfilled: true, value: 'skipped', ... }, and fetchThePage never ran
与 extendPage,方法本身停留在主机上,而不是被序列化入隔离;调用在制作时会穿过频道. 它的论点和结果仍然跨越该频道,所以两者都必须是该频道能够携带的价值:a BigInt例如,拒绝而不是解决这一呼吁.
这两种类型都可以坐在同一页上,或者算作满足了这个方法,所以只使用这些功能的函数不会启动Chromium. 两个名字上的一个是 extendPage 值,而且该主机方法无法达到.
同样的方法和论据每跑一次就能解决. 允许每跑32个不同的电话; vmOpts.maxHostCalls 更改盖子。 隔离会运行不可信代码并可以直接到达通道,因此将每个参数视为不可信输入. 每个 hostPage 值必须是函数.
选项
const myFn = createFunction(code, {
// Browserless instance factory
getBrowserless: () => require('browserless')(),
// Attempts on the `getPage` path, where there is no context to replace and
// this is the only retry. The default path takes its retry count from the
// browserless context instead.
retry: 2,
// Execution timeout in milliseconds
timeout: 30000,
// Extra methods on `page`. JSON values become async getters; functions
// are inlined as async methods. If the function only uses these methods,
// Chromium is not started.
extendPage: {
url,
html
},
// Methods on `page` the host resolves when the function calls them. The
// method stays on the host and one the function never reaches is never
// resolved, though arguments and results still cross the channel and must
// be values it can carry. Counts as satisfying that method, like extendPage.
hostPage: {
content: () => fetchThePage(url)
},
// Options passed to browserless.goto()
gotoOpts: {
scripts: ['https://cdn.example.com/library.js'],
waitUntil: 'networkidle0'
},
// VM sandbox options (passed to isolated-function)
vmOpts: { /* ... */ },
// Values for your function, spread into its argument. Never read as a
// runtime option. Must be a plain object.
args: { code: 'abc' },
// Run against a page that is already navigated, instead of creating a
// context and navigating. It replaces that path, so `getBrowserless` is not
// consulted when it is set. No `goto` happens and the page is never closed:
// whoever supplied it owns its lifetime. Pass `response` when you have it,
// so the function still sees `_response`. `timeout` bounds how long the
// caller waits. It leaves the page open, and the snippet plus its isolate
// subprocess keep running until the snippet returns or the page is closed.
// `device` and `response` are optional. Without a device, the `{ userAgent,
// viewport }` a snippet sees is read off the page, so it matches what the
// default path reports; pass your own to override it.
getPage: async () => ({ page, device, response })
})
重用已装入的呼叫器的一页, 因此目标被获取一次 .
getPage 替换上下文和辅助路径,所以 getBrowserless 没有
咨询了这一呼吁:
const { page, response } = await somethingThatAlreadyNavigated(url)
const result = await createFunction(code, {
getPage: async () => ({ page, response })
})(url)
await page.close()
片段在连接到的隔离中运行 browserWSEndpoint这样
page.browser() 访问浏览器上的每一个页面, 不只是它是一个
掌声. strictTarget 决定哪一页,不是它所能达到的。 这个
在导航路径上,它已经是真实的了, 在一个上下文中,它更为重要
跨任务共享: 将共享视为信任边界 此套件无法
强制你.
timeout 拒绝调用,并打开页面。 片断及其
隔离子进程持续运行, 所以将页面视为繁忙 : 别管它
直到工作结束,或关闭它。 关闭页面结束片断 .
从 browserless 需求 keepPage,从 evaluate
解决后立即关闭页面 :
let page
await context.evaluate(
currentPage => {
page = currentPage
return currentPage.content()
},
{ keepPage: true }
)(url)
保留一个页面会重新启动它的密切监视器 。 新窗口是
evaluate 编号 : withPage 超时,从移交中计量。 完成或关闭
在窗口结束前页。 一会儿 getPage 呼叫有自己的超时
当评价窗口结束时, 包括当
这一呼吁正在执行中。 设定评估超时时间以覆盖
后续行动.
实例
与页面元素的互动
const createFunction = require('@browserless/function')()
const code = async ({ page }) => {
await page.waitForSelector('button.submit')
await page.type('input', '[email protected]', { delay: 200 })
await page.click('button.submit')
await page.waitForNavigation()
return page.title()
}
const clickAndGetTitle = createFunction(code)
const result = await clickAndGetTitle('https://example.com')
输入外部脚本
const createFunction = require('@browserless/function')()
const code = ({ page }) => page.evaluate('jQuery.fn.jquery')
const getjQueryVersion = createFunction(code, {
gotoOpts: {
scripts: ['https://code.jquery.com/jquery-3.6.0.min.js']
}
})
const result = await getjQueryVersion('https://example.com')
// => { isFulfilled: true, value: '3.6.0', ... }
在沙盒中使用 npm 模块
const createFunction = require('@browserless/function')()
const code = async ({ page }) => {
const _ = require('lodash')
const text = await page.evaluate(() => document.body.innerText)
return _.words(text).length
}
const countWords = createFunction(code)
const result = await countWords('https://example.com')
处理错误
const createFunction = require('@browserless/function')()
const code = () => {
throw new Error('Something went wrong')
}
const myFn = createFunction(code)
const result = await myFn('https://example.com')
console.log(result.isFulfilled) // => false
console.log(result.value.message) // => 'Something went wrong'
如何适合在单体
这个 扩展功能包它没有被接入 browserless 核心 – 需要可以触摸一页的沙盒时安装.
依赖关系
| 软件包 | 目的 |
|---|---|
@browserless/errors | 错误正常化和打出错误 |
isolated-function | 通过儿童程序确保被沙箱处决 |
require-one-of | 自动检测无浏览器安装 |
acorn 编号 : acorn-walk | AST 解析以检测代码中的页面使用 |
许可证
无法浏览/ 函数 © 微链接,在 麻省理工学院 执照.
作者和维护者 微链接 由来自 捐助者。 。 。 .
微链接.io • GitHub 软件 微链克 • X @microlinkhq (英语)