Skip to content

插件开发最佳实践

本文档总结了插件开发的最佳实践,帮助您编写高质量、可维护的插件代码。

1. 代码结构规范

js
class Tool extends OPENUGC_API_V2 {
  constructor(args) {
    super(args);
    // 参数初始化
    this.validateArgs();
  }

  validateArgs() {
    // 参数验证
    if (!this.args.url) {
      throw new Error('缺少必要参数:url');
    }
  }

  async run() {
    let page;
    try {
      // 获取页面管理对象
      page = await this.OpenUrl({
        url: this.args.url,
        showLog: true
      });

      // 执行核心逻辑
      const result = await this.extractData(page);

      return result;
    } catch (error) {
      return this.handleError(error);
    } finally {
      // 始终关闭页面
      if (page) {
        page.close();
      }
    }
  }

  async extractData(page) {
    // 数据提取逻辑
    return await page.execute('...');
  }

  handleError(error) {
    // 错误处理
    return {
      success: false,
      error: error.message,
      timestamp: new Date().toISOString()
    };
  }
}

2. 错误处理策略

js
// 分层错误处理
try {
  // 页面操作
} catch (pageError) {
  console.error('页面操作失败:', pageError);
  // 重试或降级处理
}

try {
  // 数据提取
} catch (dataError) {
  console.error('数据提取失败:', dataError);
  // 返回部分数据
}

try {
  // 数据处理
} catch (processError) {
  console.error('数据处理失败:', processError);
  // 返回原始数据
}

3. 性能优化建议

js
// 1. 批量操作
const data = await page.execute(`
  // 一次性获取所有数据
  const items = Array.from(document.querySelectorAll('.item'))
    .map(item => ({
      title: item.querySelector('.title')?.innerText,
      price: item.querySelector('.price')?.innerText
    }));
  return items;
`);

// 2. 合理等待
const element = await this.waitForSelector('.target', 5000);

// 3. 及时释放
page.close();  // 使用 finally 确保执行

4. 调试技巧

js
const page = await this.OpenUrl({
  url: this.args.url,
  showLog: true  // 开启日志
});

// 在代码中添加调试信息
await page.execute(`
  console.log('页面标题:', document.title);
  console.log('URL:', window.location.href);
  console.log('元素数量:', document.querySelectorAll('.item').length);
`);

5. 常用代码片段

页面元素等待

js
// 等待元素出现
await this.waitForSelector('.target', 5000);

// 等待页面加载完成
await page.execute(`
  await new Promise(resolve => {
    if (document.readyState === 'complete') {
      resolve();
    } else {
      window.addEventListener('load', resolve);
    }
  });
`);

数据提取模板

js
// 通用数据提取
const extractData = (selector, mapper) => {
  const elements = document.querySelectorAll(selector);
  return Array.from(elements).map(mapper);
};

// 使用示例
const products = extractData('.product-item', (item) => ({
  title: item.querySelector('.title')?.innerText?.trim(),
  price: item.querySelector('.price')?.innerText?.trim(),
  url: item.querySelector('a')?.href
}));

错误重试机制

js
async function retryOperation(operation, maxRetries = 3, delay = 1000) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await operation();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await this.sleep(delay);
    }
  }
}

相关链接

Released under the MIT License.