Skip to content

浏览器探测 — 导航与执行

legado.browser 是句柄风格 API;legado.browser2 是对象风格封装,推荐优先使用。两者功能等价,可混用。

legado.browser2(对象风格,推荐)

获取会话

js
var session = legado.browser2.acquire(role, options?)  // 按角色复用会话(推荐)
var session = legado.browser2.create(options?)         // 新建独立会话(非必要不使用)
var session = legado.browser2.fromId(id)               // 从底层句柄 ID 包装
参数类型说明
rolestring会话角色标识,相同 role 复用同一会话,引擎自动管理生命周期
optionsobject可选,同 create 的 options

返回 BrowserSession 对象。

BrowserSession 方法

方法返回说明
.navigate(url, options?)void导航到 URL 并等待加载
.eval(code, options?)any在页面执行 JS
.html()string当前页面 HTML
.text()string当前页面纯文本
.url()string当前页面 URL
.cookies(cookieUrl?)array获取 Cookie 列表
.setCookie(cookieUrl, cookie)void设置 Cookie
.setUserAgent(ua)void设置 UA
.show()void显示探测窗口
.hide()void隐藏探测窗口
.mute()void静音
.unmute()void取消静音
.setMuted(muted)void设置静音状态
.onRequest(handler, options?)void注册网络请求/响应回调;options 同 legado.browser.onRequest
.offRequest()void移除网络请求回调
.postMessage(type, data?)void向页面发送消息(无需 id)
.request(type, data?, options?)any向页面发送请求并等待返回
.waitMessage(options?)object|null等待页面消息
.drainMessages()array取走全部页面消息队列
.onMessage(handler)void注册 Boa 侧消息 handler
.offMessage()void移除 Boa 侧消息 handler
.handleNextMessage(options?)object|null等待一条消息并调用 handler
.pumpMessages()number批量处理当前队列消息
.close()void关闭会话,释放资源(acquire 模式不需要调用)

legado.browser2.run

一次性操作,与 legado.browser.run 等价:

js
legado.browser2.run(url, code, options?) → any

示例:acquire 对象风格(推荐)

js
async function chapterContent(chapterUrl) {
  // acquire 自动复用同一会话,无需手动管理 globalThis
  var session = legado.browser2.acquire('content', { visible: false });
  session.navigate(chapterUrl, { waitUntil: 'load' });
  return session.eval(`
    await new Promise(function(resolve) { setTimeout(resolve, 500); });
    return document.querySelector('#content')?.innerText || '';
  `);
}

示例:acquire 角色复用

js
async function getPageHtml(url) {
  var session = legado.browser2.acquire('main', { visible: false });
  session.navigate(url, { waitUntil: 'networkidle' });
  return session.html();
}

legado.browser(句柄风格)

legado.browser.navigate

导航会话到指定 URL 并等待加载完成。

js
legado.browser.navigate(id, url, options?) → void
参数类型说明
idstring会话 ID
urlstring目标 URL
optionsobject导航选项

options

字段类型默认值说明
waitUntilstring'load'等待条件
waitForstringwaitUntil 的兼容别名
timeoutSecsnumber跟随浏览器探测设置超时秒数
timeoutnumbertimeoutSecs 的兼容别名,单位秒
timeoutMsnumber超时毫秒数,会向上取整为秒

waitUntil 值

说明
'load'等待页面加载完成事件
'domcontentloaded'等待 DOMContentLoaded 事件
'networkidle'等待 load 后网络空闲 500ms

legado.browser.eval

在页面上下文中执行 JavaScript 代码。

js
legado.browser.eval(id, code, options?) → any
参数类型说明
idstring会话 ID
codestring要执行的 JS 代码
optionsobject{ timeoutSecs?, timeout?, timeoutMs? }

返回值:代码执行结果(JSON 反序列化后的值)。

代码中可使用

  • return 语句返回值
  • await 异步操作
  • 页面上下文中的 documentwindow 等浏览器 API

示例

js
var result = legado.browser.eval(id, `
  await new Promise(function(resolve) { setTimeout(resolve, 500); });
  return document.querySelector('#content').innerText;
`);

legado.browser.run

一次性操作:创建会话 → 导航到 URL → 执行 JS → 返回结果 → 关闭会话。

js
legado.browser.run(url, code, options?) → any
参数类型说明
urlstring目标页面 URL
codestring要执行的 JS 代码
optionsobject{ visible?, waitUntil?, waitFor?, timeoutSecs?, timeout?, timeoutMs? }

示例:动态页面搜索

js
async function search(keyword, page) {
  var url = BASE + '/search?q=' + encodeURIComponent(keyword) + '&page=' + page;
  return legado.browser.run(url, `
    await new Promise(function(resolve) { setTimeout(resolve, 800); });
    return Array.from(document.querySelectorAll('.book-item')).map(function(el) {
      return {
        name: el.querySelector('.title')?.textContent?.trim() || '',
        author: el.querySelector('.author')?.textContent?.trim() || '',
        bookUrl: el.querySelector('a')?.href || '',
        coverUrl: el.querySelector('img')?.src || '',
        latestChapter: el.querySelector('.latest a')?.textContent?.trim() || '',
        latestChapterUrl: el.querySelector('.latest a')?.href || '',
        wordCount: el.querySelector('.words')?.textContent?.trim() || '',
        updateTime: el.querySelector('.updated')?.textContent?.trim() || '',
        status: el.querySelector('.status')?.textContent?.trim() || ''
      };
    });
  `, { visible: false, waitUntil: 'load', timeoutSecs: 30 });
}

示例:多步骤会话(句柄风格)

js
async function chapterContent(chapterUrl) {
  if (!globalThis.contentBrowserId) {
    globalThis.contentBrowserId = legado.browser.create({ visible: false });
  }
  var id = globalThis.contentBrowserId;

  try {
    legado.browser.navigate(id, chapterUrl, { waitUntil: 'load' });
    return legado.browser.eval(id, `
      await new Promise(function(resolve) { setTimeout(resolve, 500); });
      return document.querySelector('#content')?.innerText || '';
    `);
  } catch (e) {
    legado.browser.close(id);
    globalThis.contentBrowserId = '';
    throw e;
  }
}

基于 MIT 许可发布