Skip to content

快速开始

本指南将帮助您创建第一个 OmniBox 爬虫源。

创建爬虫源

1. 进入管理后台

  1. 打开 OmniBox 管理后台
  2. 导航到"爬虫源管理"页面
  3. 点击"新建爬虫源"按钮

2. 填写基本信息

  • 名称:爬虫源的显示名称(如:"示例视频站")
  • 类型:选择 JavaScriptPython
  • 描述:可选,描述爬虫源的功能

3. 创建脚本

系统提供了两种类型:

  • JavaScript:适用于熟悉 Node.js 的开发者
  • Python:适用于熟悉 Python 的开发者

编写第一个脚本

JavaScript 示例

javascript
// @name 示例爬虫源
// @version 1.0.0

const OmniBox = require("omnibox_sdk");
const runner = require("spider_runner");

module.exports = { home, category, detail, search, play };
runner.run(module.exports);

async function home(params, context) {
  await OmniBox.log("info", "获取首页数据");
  return {
    class: [
      { type_id: "1", type_name: "电影" },
      { type_id: "2", type_name: "电视剧" },
    ],
    list: [
      {
        vod_id: "1",
        vod_name: "示例视频",
        vod_pic: "https://example.com/pic.jpg",
        type_id: "1",
        type_name: "电影",
        vod_remarks: "HD",
        vod_year: "2024",
        vod_douban_score: "8.5",
        vod_subtitle: "2024 / 中国大陆 / 剧情",
      },
    ],
    // 可选:filters 按分类 ID 提供筛选器;banner 为首页轮播
    // filters: { "1": [{ key: "area", name: "地区", init: "全部", value: [...] }] },
    // banner: [{ title: "", subtitle: "", backgroundImage: "", genre: "", actors: "", description: "" }],
  };
}

async function category(params, context) {
  const categoryId = params.categoryId || "1";
  const page = params.page || 1;
  const filters = params.filters || {};
  return {
    page: Number(page),
    pagecount: 10,
    total: 100,
    list: [
      {
        vod_id: `${categoryId}_${page}_1`,
        vod_name: `分类视频 ${page}-1`,
        vod_pic: "https://example.com/pic.jpg",
        type_id: categoryId,
        type_name: "电影",
        vod_remarks: "HD",
        vod_year: "2024",
        vod_douban_score: "8.5",
      },
    ],
  };
}

async function detail(params, context) {
  const videoId = params.videoId;
  if (!videoId) return { list: [] };
  return {
    list: [
      {
        vod_id: videoId,
        vod_name: "示例视频详情",
        vod_pic: "https://example.com/pic.jpg",
        vod_content: "视频简介",
        vod_year: "2024",
        vod_remarks: "HD",
        vod_douban_score: "8.5",
        vod_actor: "演员A, 演员B",
        vod_director: "导演",
        vod_area: "中国大陆",
        vod_play_sources: [
          {
            name: "线路1",
            episodes: [
              { name: "第1集", playId: "ep1_play_id" },
              { name: "第2集", playId: "ep2_play_id" },
            ],
          },
        ],
      },
    ],
  };
}

async function search(params, context) {
  const keyword = params.keyword || "";
  const page = params.page || 1;
  if (!keyword) return { page: 1, pagecount: 0, total: 0, list: [] };
  return {
    page: Number(page),
    pagecount: 5,
    total: 50,
    list: [
      {
        vod_id: `search_${keyword}_1`,
        vod_name: `搜索结果: ${keyword}`,
        vod_pic: "https://example.com/pic.jpg",
        type_id: "1",
        type_name: "电影",
        vod_remarks: "HD",
        vod_year: "2024",
        vod_douban_score: "8.5",
      },
    ],
  };
}

async function play(params, context) {
  const playId = params.playId;
  const flag = params.flag || "play";
  if (!playId) throw new Error("playId 不能为空");
  return {
    urls: [{ name: "播放", url: `https://example.com/video/${playId}.m3u8` }],
    flag: flag,
    header: { "User-Agent": "Mozilla/5.0", Referer: "https://example.com/" },
    parse: 0, // 0=直链不需解析,1=需客户端嗅探(仅 ok影视 app 有效)
    // danmaku: [{ name: "弹幕", url: "https://..." }], // 可选,弹幕列表
  };
}

Python 示例

python
# -*- coding: utf-8 -*-
# @name 示例爬虫源
# @version 1.0.0

import json
from spider_runner import OmniBox, run

async def home(params, context):
    """获取首页:分类 + 推荐列表。"""
    await OmniBox.log("info", "获取首页数据")
    return {
        "class": [
            {"type_id": "1", "type_name": "电影"},
            {"type_id": "2", "type_name": "电视剧"},
        ],
        "list": [
            {
                "vod_id": "1",
                "vod_name": "示例视频",
                "vod_pic": "https://example.com/pic.jpg",
                "type_id": "1",
                "type_name": "电影",
                "vod_remarks": "HD",
                "vod_year": "2024",
                "vod_douban_score": "8.5",
            },
        ],
    }

async def category(params, context):
    """获取分类列表。"""
    category_id = params.get("categoryId") or "1"
    page = params.get("page") or 1
    filters = params.get("filters") or {}
    return {
        "page": int(page),
        "pagecount": 10,
        "total": 100,
        "list": [
            {
                "vod_id": f"{category_id}_{page}_1",
                "vod_name": f"分类视频 {page}-1",
                "vod_pic": "https://example.com/pic.jpg",
                "type_id": category_id,
                "type_name": "电影",
                "vod_remarks": "HD",
                "vod_year": "2024",
                "vod_douban_score": "8.5",
            },
        ],
    }

async def detail(params, context):
    """获取视频详情。"""
    video_id = params.get("videoId")
    if not video_id:
        return {"list": []}
    return {
        "list": [
            {
                "vod_id": video_id,
                "vod_name": "示例视频详情",
                "vod_pic": "https://example.com/pic.jpg",
                "vod_content": "视频简介",
                "vod_year": "2024",
                "vod_remarks": "HD",
                "vod_douban_score": "8.5",
                "vod_actor": "演员A, 演员B",
                "vod_director": "导演",
                "vod_area": "中国大陆",
                "vod_play_sources": [
                    {
                        "name": "线路1",
                        "episodes": [
                            {"name": "第1集", "playId": "ep1_play_id"},
                            {"name": "第2集", "playId": "ep2_play_id"},
                        ],
                    },
                ],
            },
        ],
    }

async def search(params, context):
    """搜索视频。"""
    keyword = (params.get("keyword") or params.get("wd") or "").strip()
    page = params.get("page") or 1
    if not keyword:
        return {"page": 1, "pagecount": 0, "total": 0, "list": []}
    return {
        "page": int(page),
        "pagecount": 5,
        "total": 50,
        "list": [
            {
                "vod_id": f"search_{keyword}_1",
                "vod_name": f"搜索结果: {keyword}",
                "vod_pic": "https://example.com/pic.jpg",
                "type_id": "1",
                "type_name": "电影",
                "vod_remarks": "HD",
                "vod_year": "2024",
                "vod_douban_score": "8.5",
            },
        ],
    }

async def play(params, context):
    """获取播放地址。可返回 urls、header、parse(0=直链/1=需嗅探,仅 ok影视 app)、danmaku(弹幕列表)。"""
    play_id = params.get("playId")
    flag = params.get("flag") or "play"
    if not play_id:
        raise ValueError("playId 不能为空")
    return {
        "urls": [{"name": "播放", "url": f"https://example.com/video/{play_id}.m3u8"}],
        "flag": flag,
        "header": {"User-Agent": "Mozilla/5.0", "Referer": "https://example.com/"},
        "parse": 0,  # 直链不需解析;1 表示需客户端嗅探,仅 ok影视 app 有效
    }

if __name__ == "__main__":
    run({
        "home": home,
        "category": category,
        "detail": detail,
        "search": search,
        "play": play,
    })

Python 模板使用 spider_runnerrun(handlers) 从标准输入读入请求、分发到对应 handler,无需手写 main 与 JSON 解析。参数与上下文通过 paramscontext(dict)传入,与 JS 端一致。

下一步