TVBox中的Python接口解读
在TVBox中,通过 chaquopy 实现了基于 python 爬虫的接口抽象。目前在一些更新比较频繁的类TVBox软件中均已支持,例如 Fongmi 影视、影视仓、EasyBox等。本文以 Fongmi 影视为参考,详细解读其中 Python 爬虫接口如何适配,各函数接口输入输出参数含义,使用场景等。
相关源代码见 https://github.com/FongMi/TV/tree/fongmi/chaquo/src/main/python/base/spider.py
以下内容由AI代码分析,人工验证测试后所总结。仅供参考。
init
def init(self, extend=""):
pass
init 接口主要负责初始化。
extend 入参为字符串格式,内容来自 json 配置文件中关联该py脚本的站点下的 ext 。在 json 配置文件中,你可以根据脚本需要完全自定义 ext 中的内容,例如传递网址、登录的cookie参数等等。
{
"key": "py_butailing",
"name": "不太灵",
"type": 3,
"api": "./api/butailing.py",
"searchable": 1,
"changeable": 1,
"quickSearch": 1,
"filterable": 1,
"playerType": 2,
"ext": {
"text":"ext-test",
"data":[1,2,3,4,5]
},
"style": {
"type": "rect",
"ratio":0.75
}
}
在实际运行时,最先被调用的就是 init 接口。因此你可以将一些通用的参数的初始化放在这个接口里,如 host 地址。
homeContent
def homeContent(self, filter):
pass
homeContent 接口主要负责处理站点分类、筛选以及首页视频列表。
在 TVBox 中,一个站点通常在顶部有多个可供用户选择的分类按钮,例如电影、电视、综艺等等。而在这些分类选中后,还可以提供筛选功能,例如电影可以选择动作片、恐怖片、科幻片等等。在这些分类还未选中时,首页还需要提供用于展示的视频列表信息。
filter 入参为布尔型变量,其内容来自 json 配置中的 filterable 参数,0 表示不可筛选,1 表示可筛选。
homeContent 返回的是一个 json,其格式参考如下:
{
"class": [
{
"type_name": "电影",
"type_id": 20
},
{
"type_name": "电视剧",
"type_id": 21
}
],
"filters": {
"20": [
{
"key": "class",
"name": "类型",
"value": [
{
"n": "Netflix",
"v": "Netflix"
},
{
"n": "喜剧",
"v": "喜剧"
}
]
},
{
"key": "area",
"name": "地区",
"value": [
{
"n": "大陆",
"v": "大陆"
},
{
"n": "香港",
"v": "香港"
}
]
}
],
"21": [
{
"key": "class",
"name": "类型",
"value": [
{
"n": "Netflix",
"v": "Netflix"
},
{
"n": "古装",
"v": "古装"
}
]
},
{
"key": "area",
"name": "地区",
"value": [
{
"n": "大陆",
"v": "大陆"
},
{
"n": "韩国",
"v": "韩国"
}
]
}
]
},
"list": [
{
"vod_id": 69780,
"vod_name": "绝世战魂",
"vod_pic": "https://img.ffzy888.com/upload/vod/20221114-1/4f2a3910e3f0ad0f1878eb9932ff6a33.jpg",
"vod_remarks": "更新至127集"
},
{
"vod_id": 148464,
"vod_name": "地狱旅馆",
"vod_pic": "https://img.lzzyimg.com/upload/vod/20220909-1/6a60270e5b91796482f1557d814b4fa0.jpg",
"vod_remarks": "更新至04集"
}
]
}
json 内容一共包括三大块:class、filters、list。
class 为一数组,子元素由 type_name 和 type_id 构成,type_name 为分类名称,最终显示在顶部的分类选项就是它;type_id 是用于后续识别分类的值,一般可将其与站点网址中的分类路径相关联。
filters 是一个字典,子元素的键名与class中子元素的 type_id 对应,表示在该分类下所产生的筛选选项。子元素是一个列表,因为筛选时可以有多个筛选维度。对于其中某一个维度,其内容由 key、name 、value 构成。其中 key 用于后续识别当前筛选维度,name 用于显示,value 是一个列表,筛选时有多个选项,这些选项一般是互斥的(即只能选一个)。各个选项由 n 和 v 构成。n 表示名称,用于显示,v 为用于识别选项的值。
list 是一个列表,其子元素即为每个视频的信息,通常这里的信息是简略的,只要包括链接详情页的地址id,视频标题,视频封面,视频标签(如豆瓣评分)等。这里的 vod 形式实际上参考的是 苹果cms 。

homeVideoContent
def homeVideoContent(self):
pass
homeVideoContent 主要负责处理首页的推荐视频列表,返回的是一个json,具体格式如下
{
"list": [
{
"vod_id": 69780,
"vod_name": "绝世战魂",
"vod_pic": "https://img.ffzy888.com/upload/vod/20221114-1/4f2a3910e3f0ad0f1878eb9932ff6a33.jpg",
"vod_remarks": "更新至127集"
},
{
"vod_id": 148464,
"vod_name": "地狱旅馆",
"vod_pic": "https://img.lzzyimg.com/upload/vod/20220909-1/6a60270e5b91796482f1557d814b4fa0.jpg",
"vod_remarks": "更新至04集"
}
]
}
可以看到与 homeContent中的list类似,去掉了 class 和 filters。
categoryContent
def categoryContent(self, tid, pg, filter, extend):
pass
categoryContent 主要负责处理的是分类、筛选、翻页等动作发生时,页面中所需要刷新的视频列表信息。
tid 入参是 type_id 的缩写,格式为字符串,当分类按钮被选中时, tid的值也就更新为 type_id 的值。除了这个场景外,当存在其的非分类动作产生的跳转时,tid的值会更新为跳转时由vod传递过来的 vod_id 值。
pg 入参是 page 的缩写,格式为字符串,视频列表是按页加载的,对应网站中的某一页内容,当用户滚动视频列表到底部时,会触发加载新的一页,pg自增,再次调用该接口,从而获得新的视频内容。这就类似于懒加载。
filter 入参为布尔型变量,表示是否支持筛选,内容来自 json 配置中的 filterable 参数,0 表示不可筛选,1 表示可筛选。
extend 入参是一个字典,用户点击某个筛选按钮,则这个这个按钮的 key 会被记录,value 则来自value列表中所选中的选项对应的 v 值。
通过以上参数,合理解析由用户操作所产生的包括跳转地址、分页、分类筛选等信息,构造目标网页地址,然后再自行编写网页内容爬取函数,最后返回视频列表信息。
函数最终返回的结果为 json,格式如下:
{
"list": [
{
"vod_id": 69780,
"vod_name": "绝世战魂",
"vod_pic": "https://img.ffzy888.com/upload/vod/20221114-1/4f2a3910e3f0ad0f1878eb9932ff6a33.jpg",
"vod_remarks": "更新至127集"
},
{
"vod_id": 148464,
"vod_name": "地狱旅馆",
"vod_pic": "https://img.lzzyimg.com/upload/vod/20220909-1/6a60270e5b91796482f1557d814b4fa0.jpg",
"vod_remarks": "更新至04集"
}
],
"page": "1",
"pagecount": 9999,
"limit": 90,
"total": 999999
}
其中list为视频列表,剩下的是关于页码的信息,page 表示当前是第几页,pagecount 表示一共有多少页,limit 表示超时,total表示一共多少页。
这里值得一提的是,该接口实际上可以处理类似文件夹多层级打开的功能。视频信息完整的可供解析的参数包括:
{
"vod_id": "",
"vod_name": "",
"type_name": "",
"vod_pic": "",
"vod_remarks": "",
"vod_year": "",
"vod_area": "",
"vod_director": "",
"vod_actor": "",
"vod_content": "",
"vod_play_from": "",
"vod_play_url": "",
"vod_wallpaper": "",
"vod_tag": "",
"action": "",
"cate": "",
"style": "",
"land": "",
"circle": "",
"ratio": ""
}
其中 vod_tag 有两种选项:file 、folder,如果是folder则表示点击该视频封面后,会将vod_id 作为新的 tid 继续调用 本接口,从而形成多层点击,直到返回的视频 vod_tag 为 file,再点击时才调用 detailContent 。
所以在处理入参,构造待解析的网址时,需要处理好url合成的逻辑,因为这里可能存在很多场景共用这一个接口的问题。
另外视频的封面尺寸实际上可以在本接口中直接调整,通过style参数控制,具体参数包括:
//直式
{
"style": {
"type": "rect"
}
}
//橫式
{
"style": {
"type": "rect",
"ratio": 1.33
}
}
//正方
{
"style": {
"type": "rect",
"ratio": 1
}
}
//正圓
{
"style": {
"type": "oval"
}
}
//橢圓
{
"style": {
"type": "oval",
"ratio": 1.1
}
}
detailContent
def detailContent(self, ids):
pass
detailContent 主要负责处理某个视频页网址的视频详细信息爬取。
ids 入参默认是一个列表,但是一般我们只取第一个元素作为视频页地址。
在这个接口中,需要获取视频的详细信息,最终接口返回 json,格式如下:
{
"list": [
{
"vod_name": "爱的小麻烦",
"vod_pic": "https://api.codetabs.com/v1/proxy/?quest=https://img.cfwebname.top/i/2025/08/15/689e94507a6a5.png",
"vod_year": "2020",
"vod_director": "罗伯托·菲斯科",
"vod_actor": "阿方索·杜萨勒,瑞吉娜·布兰登,Francesca Mercadante",
"type_name": "喜剧",
"vod_area": "墨西哥",
"vod_content": " 他全心爱上的女子竟然讨厌小孩!这下如何是好?9 岁的女儿提议假装成他的妹妹,应该不会有什麽问题吧?",
"vod_play_from": "WEB-1080P$$$其他",
"vod_play_url": "磁力$magnet:?xt=urn:btih:69A166E5CFACB8C24B2280D96395F15556737024#磁力$magnet:?xt=urn:btih:74EE1CA8F44788A68895C3CDA07C9F3A68D3B66A#磁力$magnet:?xt=urn:btih:A866D12DC828C7C0DD9AB31A348186F2E4025ED0$$$磁力$magnet:?xt=urn:btih:42F4AF63FE801EEC9F9941BE13F1A743DC0A379A"
}
]
}
视频资源
这里要重点解释的是 vod_play_from 和 vod_play_url 这两个是绑定在一起的,其内容语法来自 苹果cms 。在苹果cms中,通过下面这种语法表示一个视频资源:
视频名称$视频链接
当有多个视频资源时(通常在电视剧资源时表示视频集数),通过#串联。不同线路通过 $$$ 串联。上述vod_play_from 表示路线,vod_play_url 表示该路线下对应的资源。这里的视频链接可以是直接播放的直链,也可以是某个可解析出视频直链的地址,这样在 playerContent 接口中需要写解析方法。
富文本
在 FongMi 影视中,允许在 vod_director、vod_actor、vod_content等内容中插入富文本链接,软件中带有富文本链接的内容会变黄色,带有下划线。富文本格式如下:
content = f'[a=cr:{{"id":"{href}","name":"{name}"}}/]{name}[/a]'
其中href为跳转的链接,类似 vod_id 功能,name用于显示。
当点击该富文本链接时,会将href作为跳转tid,再次调用 categoryContent 。
playerContent
def playerContent(self, flag, id, vipFlags):
pass
playerContent 主要负责处理播放视频时视频的资源地址解析。
id 入参即为detailContent 中传入的某个视频链接地址。
flag 入参即为detailContent 中传入的某个视频链接对应的vod_play_from参数。
vipFlags 入参目前尚未看到有开源的接口源有用到的。
接口返回的结果为json,格式如下:
{
"jx":1,
"parse": 0,
"url": "https://tyyszywvod5.com/videos/202507/03/68669eb47ea4833d7f00048e/ae77de/index.m3u8",
"header": {
"User-Agent": "okhttp/3.14.9"
}
}
其中 jx 表示用第几个解析接口,parse表示是否需要解析。url为需要播放的地址。header 可有可无。
searchContent
def searContent(self, key, quick, pg="1"):
pass
searchContent 主要处理站点内容搜索返回视频列表。
key 入参即为搜索框输入的文本内容。
quick 为布尔型变量,表示是否启用快速搜索。
pg 表示页码,可能存在多页搜索结果。
该接口与前面的接口类似,只是从搜索页的网址中获取视频列表,返回结果也为json,具体如下:
{
"list": [
{
"vod_name": "爱的小麻烦",
"vod_pic": "https://api.codetabs.com/v1/proxy/?quest=https://img.cfwebname.top/i/2025/08/15/689e94507a6a5.png",
"vod_year": "2020",
"vod_director": "罗伯托·菲斯科",
"vod_actor": "阿方索·杜萨勒,瑞吉娜·布兰登,Francesca Mercadante",
"type_name": "喜剧",
"vod_area": "墨西哥",
"vod_content": " 他全心爱上的女子竟然讨厌小孩!这下如何是好?9 岁的女儿提议假装成他的妹妹,应该不会有什麽问题吧?",
"vod_play_from": "WEB-1080P$$$其他",
"vod_play_url": "磁力$magnet:?xt=urn:btih:69A166E5CFACB8C24B2280D96395F15556737024#磁力$magnet:?xt=urn:btih:74EE1CA8F44788A68895C3CDA07C9F3A68D3B66A#磁力$magnet:?xt=urn:btih:A866D12DC828C7C0DD9AB31A348186F2E4025ED0$$$磁力$magnet:?xt=urn:btih:42F4AF63FE801EEC9F9941BE13F1A743DC0A379A"
}
],
"page":"1"
}
其他
其他还有很多接口,用于辅助的,例如日志打印的log,结合Fongmi的调试功能可以打印一些关键信息用于脚本开发调试。
再比如缓存相关的,getCache、setCache、delCache。获取网页内容的fetch等等。
以上辅助接口功能单一比较好理解,在此不再赘述。

在TVBox中,通过 chaquopy 实现了基于 python 爬虫的接口抽象。目前在一些更新比较频繁的类TVBox软件中均已支持,例如 Fongmi 影视、影视仓等。本文以 Fongmi 影视为参考,详细解读其中 Python 爬虫接口如何适配,各函数接口输入输出参数含义,使用场景等。
浙公网安备 33010602011771号