# uni-polymerize **Repository Path**: yangmain/uni-polymerize ## Basic Information - **Project Name**: uni-polymerize - **Description**: 基于uni-app 聚合资源的app - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 12 - **Created**: 2023-07-26 - **Last Updated**: 2023-07-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README #应用介绍 * 1、该项目为聚合资源APP,暂只支持安卓APP * 2、聚合资源包括小说、漫画、视频、直播、文章、论坛、音乐等 * 3、该项目支持加载外部来源,也支持内置来源 * 4、如果想要自己制作来源,建议先以内置来源的方式制作来源,制作完成后在来源设置中选择导出来源 * 5、为了方便调试请求,可以在设置页面 => 通用设置 => 打开调试模式,会在全局生成一个调试按钮,点击可以查看请求信息 * 6、为避免版权问题,该项目已不提供内置源 * 7、有什么不懂的,可以加群 1087735942 聊 #免责声明 * 本免责声明(以下简称“免责声明”或“本声明”)适用于好用聚合项目(以下简称"好用聚合"),在使用人及组织(以下简称"使用者")阅读本声明后若不同意此声明中的任何条款,或对本声明存在质疑,请立刻停止使用此项目。若您已经开始或正在使用此项目,则表示您已阅读并同意本声明的所有条款之约定。 * 1.使用者通过任何形式或方式使用好用聚合即表示您已经同意本声明,本声明立即自动生效。 * 2.使用者使用好用聚合自行承担风险,作者不做任何形式的保证, 因代码质量、系统BUG等任何技术原因而引起的问题,作者也不承担任何法律责任。 * 3.使用者保证好用聚合不用于任何违法犯罪行为,如传播色情、赌博等。 * 4.使用者保证好用聚合所展示内容不涉及版权或隐私等问题。 * 5.使用者保证好用聚合不用于任何商业或盈利等行为。 * 6.使用者使用好用聚合违反上述任何行为所造成的一切后果均由使用者承担。 #添加内置来源 * 第一步、将写好的来源JS文件放在/assets/api/source/文件夹下,文件名不能为中文 (注意APP导出的来源文件为JSON文件,不能用来添加内置来源) * 第二步、在/assets/api/source.js文件中引入新添加来源JS文件即可 #添加外部来源 * 添加本地来源 - 将来源JSON文件放入手机存储 => 在来源设置页面点击右上角按钮 => 在选项列表中选择导入本地来源 => 找到手机存储中的来源JSON文件 => 单击选择单个文件/长按选择多个文件 => 等待来源导入完成 * 添加网络来源 - 在来源设置页面点击右上角按钮 => 在选项列表中选择导入网络来源 => 在弹出框中输入接口地址 => 点击确定 => 等待来源导入完成 - 网络来源接口地址返回数据结构如下: ```javascript { statusCode: 200, data: { list: [来源数据1,来源数据2,来源数据3]//来源JSON文件的文本内容集合 } } ``` #来源结构 * 请注意此处为大致结构,不代表实际效果 ```javascript { "id": "",//来源ID 必填 "title": "",//来源名称 必填 "logo": "",//来源图标 "href": "",//来源域名 必填 "interval": 0,//请求时间间隔(ms) "security": "",//防盗链域名,多个以逗号分割 "isAdult": false,//是否包含敏感内容 必填 "cover": "",//默认资源封面,多个以逗号分割 "custom": {//自定义方法,存放一些常用的方法,比如签名生成 "test": function (arg) {//演示 return arg } }, "request": {//来源请求 "getHotList": {//获取首页的推荐列表,实际方法名应该要加上横杠和类型 比如小说的首页推荐列表则是 getHotList_novel 请求类型参考资源类型、合集类型和用户类型 "label": "热门列表",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口,需要请求之后才能得到请求下一页需要的参数,通过该参数返回,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getRankList": {//获取榜单列表,实际方法名应该要加上横杠和类型 比如小说的榜单列表则是 getRankList_novel 请求类型参考资源类型、合集类型和用户类型 "label": "榜单列表",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口,需要请求之后才能得到请求下一页需要的参数,通过该参数返回,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getDynamicList": {//获取动态列表,实际方法名应该要加上横杠和类型 比如小说的动态列表则是 getDynamicList_novel 请求类型参考资源类型、合集类型和用户类型 "label": "动态列表",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口,需要请求之后才能得到请求下一页需要的参数,通过该参数返回,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getFindList": {//获取发现列表,实际方法名应该要加上横杠和类型 比如短视频的发现列表则是 getFindList_short 请求类型参考资源类型、合集类型和用户类型 "label": "发现列表",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口,需要请求之后才能得到请求下一页需要的参数,通过该参数返回,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "search": {//搜索列表,实际方法名应该要加上横杠和类型 比如搜索小说则是 search_novel 请求类型参考资源类型、合集类型和用户类型 "label": "搜索列表",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口,需要请求之后才能得到请求下一页需要的参数,通过该参数返回,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getKeyword": {//搜索关键词,实际方法名应该要加上横杠和类型 比如小说关键词则是 getKeyword_novel 请求类型参考来源类型 "label": "搜索关键词",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口,需要请求之后才能得到请求下一页需要的参数,通过该参数返回,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getFilterList": {//筛选列表/分类列表,实际方法名应该要加上横杠和类型 比如小说分类列表则是 getFilterList_novel 请求类型参考资源类型、合集类型和用户类型 "label": "筛选列表",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口,需要请求之后才能得到请求下一页需要的参数,通过该参数返回,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getFilterDetail": {//筛选详情/分类详情,实际方法名应该要加上横杠和类型 比如小说分类详情则是 getFilterDetail_novel 请求类型参考资源类型、合集类型和用户类型 "label": "筛选详情",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口,需要请求之后才能得到请求下一页需要的参数,通过该参数返回,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getGatherDetail": {//合集详情,实际方法名应该要加上横杠和类型 比如书单详情则是 getGatherDetail_novels 请求类型参考合集类型表 "label": "合集详情",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效且value不会返回res 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回一个字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 data: res.data.info//详情信息 返回对象 } } }, "getGatherWorksList": {//合集详情,实际方法名应该要加上横杠和类型 比如书单详情则是 getGatherWorksList_novels 请求类型参考合集类型 "label": "合集作品列表",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "inherit": false,//是否继承getGatherDetail的请求结果(减少请求次数) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口,需要请求之后才能得到请求下一页需要的参数,通过该参数返回,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getCharacterDetail": {//用户详情,实际方法名应该要加上横杠和类型 比如写手详情则是 getCharacterDetail_writer 请求类型参考用户类型 "label": "用户详情",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效且value不会返回res 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回一个字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 data: res.data.info//详情信息 返回对象 } } }, "getCharacterWorksList": {//用户作品列表,实际方法名应该要加上用户类型和作品类型 比如写手小说作品列表则是 getCharacterWorksList_writer_novel 请求类型参考资源类型、合集类型 "label": "用户作品列表",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "inherit": false,//是否继承getCharacterDetail的请求结果(减少请求次数) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口需要请求之后才能得到请求下一页需要的参数,通过该参数返回这些参数,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getCharacterFolloweeList": {//用户关注列表,实际方法名应该要加上横杠和类型 比如写手关注列表则是 getCharacterFolloweeList_writer 请求类型参考用户类型 "label": "用户关注列表",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "inherit": false,//是否继承getCharacterDetail的请求结果(减少请求次数) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口需要请求之后才能得到请求下一页需要的参数,通过该参数返回这些参数,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getCharacterFollowerList": {//用户粉丝列表,实际方法名应该要加上横杠和类型 比如写手粉丝列表则是 getCharacterFollowerList_writer 请求类型参考用户类型 "label": "用户粉丝列表",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "inherit": false,//是否继承getCharacterDetail的请求结果(减少请求次数) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口需要请求之后才能得到请求下一页需要的参数,通过该参数返回这些参数,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getSingleDetail": {//资源详情,实际方法名应该要加上横杠和类型 比如小说详情则是 getSingleDetail_novel 请求类型参考资源类型 "label": "资源详情",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效且value不会返回res 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回一个字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 data: res.data.info,//详情信息 返回对象 sections: res.data.sections//分段列表,返回数组,部分资源会分段展示,比如小说、漫画会分章节,影视番剧会分集数,壁纸会存在分页 } } }, "getSectionDetail": {//资源分段详情,实际方法名应该要加上横杠和类型 比如小说章节详情则是 getSectionDetail_novel 请求类型参考资源类型 "label": "资源分段详情",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效且value不会返回res 必填 "interval": 0,//请求时间间隔(ms) "inherit": false,//是否继承getSingleDetail的请求结果(减少请求次数) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回一个字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 //模拟返回结果 资源为话题、文章或者资讯时返回数组 return { list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口需要请求之后才能得到请求下一页需要的参数,通过该参数返回这些参数,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } //模拟返回结果 资源为小说、漫画、壁纸、视频时返回对象 return { data: res.data.info//详情信息,返回对象 } } }, "getComment": {//评论列表,实际方法名应该要加上横杠和类型 比如小说评论列表则是 getComment_novel 请求类型参考资源类型、合集类型 "label": "评论列表",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "inherit": false,//是否继承getSingleDetail或者getGatherDetail的请求结果(减少请求次数) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口需要请求之后才能得到请求下一页需要的参数,通过该参数返回这些参数,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getRecome": {//推荐列表,实际方法名应该要加上横杠和类型 比如小说推荐列表则是 getRecome_novel 请求类型参考资源类型、合集类型表 "label": "推荐列表",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效 必填 "interval": 0,//请求时间间隔(ms) "inherit": false,//是否继承getSingleDetail或者getGatherDetail的请求结果(减少请求次数) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 list: res.data.list,//列表数据,返回数组 paging: { nextPage: res.data.nextPage//模拟参数,你可以返回任意单一或多个参数 },//分页信息,返回对象,部分分页接口需要请求之后才能得到请求下一页需要的参数,通过该参数返回这些参数,可以在params中得到 isLastPage: true//是否是最后一页,返回布尔值,true表示已经请求完毕 } } }, "getSocketDetail": {//WebSocket信息,实际方法名应该要加上横杠和类型 比如直播WebSocket信息则是 getSocketDetail_live 请求类型参考资源类型 目前该方法仅支持直播 "label": "WebSocket信息",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效且value不会返回res 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回一个字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 data: res.data.info,//详情信息 返回对象 send: res.data.send,//第一次发送消息 WebSocket连接成功后,发送一次消息,不传则不发 heartbeat: res.data.heartbeat,//心跳任务消息 WebSocket连接成功后,开始心跳任务,不传则没有心跳任务 heartbeattime: res.data.heartbeattime//心跳任务间隔时间 单位为ms } } }, "handleSocketMessage": {//处理WebSocket接受到的信息,目前该方法仅支持处理直播弹幕 "label": "处理Websocket信息",//标题 必填 "charset": "utf8",//请求格式 支持utf8/gbk 必填 "method": "get",//请求类型 支持get/post/none 当请求类型为none时url、params和headers不会生效且value不会返回res 必填 "interval": 0,//请求时间间隔(ms) "url": function(context, params) { return 'https://www.baidu.com' },//请求链接, 返回一个字符串, context为内置方法和自定义方法集合,params为请求参数 不填默认返回href "params": function(context, params) { return {page: 1} },//请求参数, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数 "headers": function(context, params) { return {Referer: 'https://www.baidu.com'} },//请求头, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数 "value": function(context, params, res) {//处理回调, 返回一个对象, context为内置方法和自定义方法集合,params为请求参数,res为请求返回结果 必填 return {//模拟返回结果 barrages: res.data.barrages,//详情信息 返回对象 } } } } } ``` #资源类型 | 类型 | 名称 | | :----- | :----: | | novel | 小说 | | comic | 漫画 | | wallpaper | 壁纸 | | figure | 套图 | | portrait | 写真 | | movie | 影视 | | drama | 连续剧 | | anime | 番剧 | | variety | 综艺 | | short | 短视频 | | mv | MV | | song | 歌曲 | | program | 节目 | | article | 文章 | | news | 资讯 | | talk | 话题 | | live | 直播 | | broadcast | 广播 | #合集类型 | 类型 | 名称 | | :----- | :----: | | novels | 书单 | | comics | 漫集 | | audible | 有声书 | | songlist | 歌单 | | songalbum | 专辑 | | mvs | MV集 | | wallpapers | 壁纸集 | | figures | 套图集 | | portraits | 写真集 | | movies | 电影集 | | dramas | 连续剧集 | | animes | 番剧集 | | varietys | 综艺集 | | shorts | 短片集 | | lives | 直播集 | | broadcasts | 广播集 | | articles | 文章集 | | newss | 新闻集 | | talks | 话题集 | | rank | 榜单 | #用户类型 | 类型 | 名称 | | :----- | :----: | | singer | 歌手 | | writer | 写手 | | uploader | UP | | anchor | 主播 | | painter | 画师 | | blogger | 博主 | | actor | 演员 | | announcer | 播音员 | #context参数 * 来源custom中的自定义方法可通过该参数取到 | 方法名 | 参数 | 说明 | | :--- | :---: | -------: | | request | --- | 封装的请求,包含 http 和 xhr 2个属性 request.http.get(url);request.xhr.get(url); | | HTMLParser | HTML文本 | 解析HTML文本,用于获取HTML文本中的数据 详情[HTMLParser HTML 文本解析器](https://ext.dcloud.net.cn/plugin?id=263) | | gb2312 | UTF-8格式的字符串 | 将UTF-8的字符转化为GBK字符串 | | Base64 | --- | Base64方法 Base64.encode('dankogai'); Base64.decode('ZGFua29nYWk='); | | Single | --- | 封装的资源类 new Single({ singleId: '131231', title: '小说名称', type: 'novel', source: 'linovel' }) | | Gather | --- | 封装的合集类 new Gather({ gatherId: '131231', title: '书单名称', type: 'novels', source: 'linovel' }) | | Character | --- | 封装的用户类 new Character({ characterId: '131231', name: '用户名称', type: 'writer', source: 'linovel' }) | | Section | --- | 封装的资源分段类 new Section({ sectionId: '131231', title: '章节名称', chapter: 1, type: 'novel', source: 'linovel' }) | | Comment | --- | 封装的评论类 new Comment({ commentId: '131231', title: '评论标题', content: '评论内容', source: 'linovel' }) | | Barrage | --- | 封装的弹幕类 new Barrage({ barrageId: '131231', name: '发送人', text: '发送内容', color: '内容颜色', time: '发送时间', source: 'linovel' }) | | replaceHTML | --- | 替换HTML字符串中的特殊字符,该方法已弃用 | | htmlDecodeByRegExp | --- | 转义HTML字符串中的一些转义序列 | | uncode | --- | 将16进制转为字符 | | dateFormat | --- | 时间格式化工具 | | convertUrlQueryObject | --- | 获取href链接中的参数,返回对象 | | time2seconds | --- | 时间转秒数工具 | | CryptoJS | --- | CryptoJS工具 | | regmatchhtml | --- | 正则匹配HTML字符,该方法已弃用 | | regmatchstr | --- | 正则匹配字符,该方法已弃用 | #params参数 * 固定参数 | 属性名 | 类型 | 说明 | | :--- | :--: | --------: | | currentPage | Number | 请求页码,仅在分页请求中存在 | | sort | String | 排序方式,仅在部分接口中存在,包括{default: '默认排序', newest: '最近更新', most: '最多人看', hottest: '热度最高'},发现列表接口排序方式包括{recome: '推荐', samecity: '同城'} | | paging | Object | 分页信息,仅在分页请求中存在 | | baseUrl | String | 来源中的基础域名href | | source | String | 来源ID | * 非固定参数 - 不同请求类型及请求方法参数也会有所改变 - 比如请求小说详情的方法为 getSingleDetail_novel 则请求参数应该为固定参数加上小说详情 即 Object.assign({}, new Single(小说), {baseUrl: 'https://www.baiduc.com', source: 'linovel'}) - 比如请求书单详情的方法为 getGatherDetail_novels 则请求参数应该为固定参数加上书单详情 即 Object.assign({}, new Gather(书单), {baseUrl: 'https://www.baiduc.com', source: 'linovel'}) - 比如请求写手详情的方法为 getCharacterDetail_writer 则请求参数应该为固定参数加上写手详情 即 Object.assign({}, new Charater(写手), {baseUrl: 'https://www.baiduc.com', source: 'linovel'}) - 其余请求方法参数以此类推 #构造函数 ```javascript //资源类 class Single { this.id = id || ((singleId || '') + '_' + source)//资源唯一ID 必填 如果填了singleId 可以不填 this.title = title || ''//名称 this.singleId = singleId || ''//资源ID this.commentId = commentId || ''//评论ID this.lyricId = lyricId || ''//歌词ID this.barrageId = barrageId || ''//弹幕ID this.src = src || ''//路径 this.comments = comments || []//评论列表 this.characters = characters || []//相关用户列表 this.lyrics = lyrics || []//歌词 this.barrages = barrages || []//弹幕 this.list = list || []//相关作品列表(可以是图片链接,也可以是歌曲或者其它资源) this.sections = sections || []//分段内容(例如章节,分集等) this.downloadUrl = downloadUrl || ''//下载链接 this.shareUrl = shareUrl || ''//分享链接 this.cover = cover || ''//封面 this.creator = creator || ''//创作者 this.avatar = avatar || ''//创作者头像 this.desc = desc || ''//介绍 this.content = content || ''//内容 this.isPay = isPay || false//是否付费 this.isLiving = isLiving?.toString() == 'false' ? false : (isLiving || true)//正在直播 this.readnum = readnum || 0//阅读次数 this.popular = popular || 0//热度 this.collect = collect || 0//收藏数 this.comment = comment || 0//评论数 this.thumbs = thumbs || 0//点赞数 this.isEnd = isEnd || false//是否完结 this.latest = latest || ''//最新更新 this.duration = duration || 0//播放时长 this.size = size || ''//大小 this.style = style || ''//风格 this.vertical = vertical || false//是否竖屏 this.tag = tag || []//标签 this.isAdult = isAdult || false//是否青壮年内容 this.record = record || {}//记录 this.mark = mark || []//书签 this.extra = extra || {}//附加字段 this.formats = formats || 'auto'//视频格式 this.type = type//资源类型 this.createTime = createTime || dateFormat(new Date().getTime())//创建时间 this.updateTime = updateTime || ''//更新时间 this.source = source || 'local'//来源 } //合集类 class Gather { this.id = id || ((gatherId || '') + '_' + source)//资源唯一ID 必填 如果填了gatherId 可以不填 this.gatherId = gatherId || '' //集合ID this.commentId = commentId || '' //评论ID this.title = title || ''//名称 this.cover = cover || '' //封面 this.desc = desc || '' //介绍 this.list = list || [] //集合列表 this.characters = characters || []//相关用户列表 this.comments = comments || []//评论列表 this.creator = creator || '' //创建者 this.avatar = avatar || ''//创建者头像 this.isPay = isPay || false//是否支付观看 this.readnum = readnum || 0 //查看次数 this.popular = popular || 0//热度 this.collect = collect || 0//收藏数 this.comment = comment || 0//评论数 this.thumbs = thumbs || 0//点赞数 this.latest = latest || ''//最后更新 this.style = style || ''//风格 this.tag = tag || []//标签 this.isAdult = isAdult || false//是否青壮年内容 this.record = record || {} //历史记录 this.extra = extra || {} //附加字段 this.type = type//类型 this.createTime = createTime || dateFormat(new Date().getTime())//创建时间 this.updateTime = updateTime || ''//更新时间 this.source = source || 'local' //来源 } //分段类 class Section { this.id = id || ((sectionId || '') + '_' + source)//资源唯一ID 必填 如果填了sectionId 可以不填 this.sectionId = sectionId || ''//分段ID this.commentId = commentId || ''//评论ID this.barrageId = barrageId || ''//弹幕ID this.title = title || ''//标题 this.chapter = chapter//序号 this.creator = creator || ''//创建者 this.src = src || ''//链接 this.barrages = barrages || []//弹幕集合 this.cover = cover || ''//封面 this.size = size || ''//大小 this.desc = desc || ''//介绍 this.isStart = isStart || false this.isEnd = isEnd || false this.content = content || null this.vertical = vertical || false//是否竖屏 this.isPay = isPay || false//否需要支付观看 this.isAdult = isAdult || false//是否青壮年内容 this.formats = formats || 'auto'//视频格式 this.startTime = startTime || 0//开始时间 this.endTime = endTime || 0//结束时间 this.type = type || ''//类型 this.extra = extra || {}//附加字段 this.source = source//来源 } //用户类 class Character { this.id = id || ((characterId || '') + '_' + source)//资源唯一ID 必填 如果填了characterId 可以不填 this.characterId = characterId || ''//角色ID this.commentId = commentId || ''//评论ID this.followeeId = followeeId || ''//关注者列表ID this.followerId = followerId || ''//跟随者列表ID this.name = name || '佚名'//名称 this.avatar = avatar || ''//头像 this.cover = cover || ''//封面 this.desc = desc || ''//介绍 this.list = list || []//作品集合 this.followee = followee || 0//关注者数量 this.follower = follower || 0//跟随者数量 this.works = works || 0//作品数量 this.style = style || ''//风格 this.isAdult = isAdult || false//是否青壮年内容 this.tag = tag || []//标签 this.extra = extra || {}//附加字段 this.type = type//用户类型 this.createTime = createTime || dateFormat(new Date().getTime())//创建时间 this.updateTime = updateTime || ''//更新时间 this.source = source//来源 } //评论类 class Comment { this.id = id || ((commentId || '') + '_' + source)//资源唯一ID 必填 如果填了commentId 可以不填 this.commentId = commentId || ''//评论ID this.avatar = avatar || ''//评论人头像 this.title = title || ''//评论人姓名或者其它相关标题 this.subtitle = subtitle || ''//评论时间或者其它二级标题 this.content = content || ''//评论时内容 this.subComment = subComment || []//子评论合集 this.masterComment = masterComment || []//父评论合集 this.type = 'comment'//类型 this.extra = extra || {}//附加字段 this.source = source || 'local'//来源 } //弹幕类 class Barrage { this.id = id || ((barrageId || '') + '_' + source)//资源唯一ID 必填 如果填了barrageId 可以不填 this.barrageId = barrageId || ''//弹幕ID this.avatar = avatar || ''//发送人头像 this.name = name || ''//发送人名称 this.text = text || ''//内容 this.color = color || '#ffffff'//弹幕内容颜色 this.time = time || 0//弹幕显示时间(单位是s) this.type = type || 'user'//类型 this.extra = extra || {}//附加字段 this.source = source || 'local'//来源 } ``` #制作来源实际操作(只是模拟内置来源制作,不是真实请求) * 以请求小说为例,模拟进行内置来源制作,其余类型也会挑重点部分讲解 * 首先按照顶部提供的添加内置来源的方式添加好内置来源,然后在来源文件中填写各种信息,如下所示: ```javascript export default { "id": "testbook", "title": "测试小说网站", "logo": "https://www.book.com/favicon.ico", "href": "https://www.book.com", "interval": 100,//100毫秒的时间间隔 "security": "images.book.com,images2.book.com",//防盗链域名,多个以逗号分割 "isAdult": false, "cover": "https://images.book.com/upload/default.png",//默认资源封面,多个以逗号分割 "custom": { "userAvatar": function (id) {//模拟生成用户头像 return 'https://images.book.com/upload/' + id + '.png' } }, "request": {}//请求方法 } ``` * 填写好基础信息后开始填写请求方法 (不同类型的请求可以同时存在) * getHotList 获取首页推荐集合列表 因为是请求小说类型,所以实际应该是getHotList_novel,请求类型参考资源类型、合集类型和用户类型 * 假设有一个小说网站首页:https://www.book.com, 其HTML源代码如下: ```html 测试小说网 ``` ```javascript //...此处省略 "getHotList_novel": { "label": "获取热门小说列表", "charset": "utf8", "method": "get", "interval": 0, "url": "",//此处不填表示返回填写的href链接 即https://www.book.com "params": ""//没有参数则不传, "headers": function(context, params) { const { baseUrl//填写的herf域名 } = params return { Host: baseUrl.replace('https://', '')//部分网页可能会验证Host 这只是一种模拟,如果网站不会验证Host则不需要传 } }, "value": function(context, params, res) { const { baseUrl, source } = params const { HTMLparser, Single } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let uls = document.getElementsByClassName('box')//获取class为box的所有html标签及其子内容 uls.forEach(ul => { let uldoc = new HTMLparser(ul['innerHTML'].tirm()) let aa = uldoc.getElementsByTagName('a') aa.forEach(a => { let adoc = new HTMLparser(a['innerHTML'].tirm()) let img = adoc.getElementsByClassName('cover')[0] let p = adoc.getElementsByClassName('desc')[0] let span = adoc.getElementsByClassName('author')[0] list.push( new Single({ singleId: a.attributes.href.replace('/book/', ''), title: a.attributes.title,//标题 cover: baseUrl + img.attributes.src,//封面 creator: span['innerHTML'].trim(),//作者 desc: p['innerHTML'].trim(),//简介 type: 'novel',//小说类型 source: source//填入该小说的来源 }) ) }) }) return { list: list,//返回list isLastPage: true//不存在分页,直接结束请求 } } } //...此处省略 ``` * getRankList 获取榜单集合列表 因为是请求小说类型,所以实际应该是getRankList_novel,参考资源类型表、合集类型表、用户类型表 * 假如有一个小说网站排行页:https://www.book.com/rank,其HTML源代码如下: ```html 测试小说网排行榜

总榜

所有小说排行榜

玄幻榜

玄幻小说排行榜

穿越榜

穿越小说排行榜

``` ```javascript //...此处省略 "getRankList_novel": { "label": "获取小说榜单列表", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl//填写的herf域名 } = params return baseUrl + '/rank' }, "params": ""//没有参数则不传, "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { HTMLparser, Gather } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let ranks = document.getElementsByClassName('rank')//获取class为rank的所有html标签及其子内容 ranks.forEach(rank => { let rankdoc = new HTMLparser(rank['innerHTML'].tirm()) let a = rankdoc.getElementsByTagName('a')[0] let h2 = rankdoc.getElementsByTagName('h2')[0] let p = rankdoc.getElementsByClassName('desc')[0] let img = rankdoc.getElementsByClassName('cover')[0] list.push( new Gather({ gatherId: a.attributes.href.replace('/rank/', ''), //榜单ID title: h2['innerHTML'].trim(),//标题 cover: baseUrl + img.attributes.src,//封面 desc: p['innerHTML'].trim(), type: 'rank',//榜单类型 source: source//填入该榜单的来源 }) ) }) return { list: list,//返回list isLastPage: true//不存在分页,直接结束请求 } } } //...此处省略 ``` * getGatherDetail 合集详情 假设合集类型为榜单,所以实际应该是getGatherDetail_rank,参考 合集类型表 * 假如有一个网站小说榜单信息页:https://www.book.com/rank/榜单ID, 其HTML源代码如下: ```html 榜单信息

小说总榜

简介:小说热门排行榜。每周一更新
``` ```javascript //...此处省略 "getGatherDetail_rank": { "label": "榜单详情", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl,//填写的herf域名 gatherId//榜单ID } = params return baseUrl + '/user/' + gatherId }, "params": "", "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { HTMLparser } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let info = document.getElementById('rankInfo')//获取id为rankInfo的所有html标签及其子内容 let infodoc = new HTMLparser(info['innerHTML'].tirm()) let name = infodoc.getElementsByClassName('name')[0]//获取榜单标题 let desc = infodoc.getElementsByClassName('desc')[0]//获取榜单简介 return { data: {//这个data的属性与请求方法有关,比如请求为getGatherDetail,则返回Gather类中的属性,有值就传,没有就不传 title: title['innerHTML'].trim(),//返回榜单标题 desc: desc['innerHTML'].trim()//返回简介标题 }//返回对象 } } } //...此处省略 ``` * getGatherWorksList 获取合集作品列表 因为是请求榜单类型,所以实际应该是getGatherWorksList_rank,参考合集类型表 * 假如有一个小说网站排行榜详情页:https://www.book.com/rank/排行榜ID?page=页码, 其HTML源代码如下: ```html 测试小说网玄幻榜 ``` ```javascript //...此处省略 "getGatherWorksList_rank": { "label": "获取榜单集合作品列表", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl,//填写的herf域名 gatherId//合集ID } = params return baseUrl + '/rank/' + gatherId }, "params": function(context, params) { const { currentPage//页码 } = params return { page: currentPage } }, "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { HTMLparser, Single } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let box = document.getElementsByClassName('box')[0]//获取class为box的所有html标签及其子内容 let aa = new HTMLparser(box['innerHTML'].tirm()).getElementsByTagName('a') aa.forEach(a => { let adoc = new HTMLparser(a['innerHTML'].tirm()) let img = adoc.getElementsByClassName('cover')[0] let p = adoc.getElementsByClassName('desc')[0] let span = adoc.getElementsByClassName('author')[0] list[list.length-1].list.push( new Single({ singleId: a.attributes.href.replace('/book/', ''), title: a.attributes.title,//标题 cover: baseUrl + img.attributes.src,//封面 creator: span['innerHTML'].trim(),//作者 desc: p['innerHTML'].trim(),//简介 type: 'novel',//小说类型 source: source//填入该小说的来源 }) ) }) return { list: list,//返回list isLastPage: list.length < 10//假设存在分页每页数据为10,则当数据数量小于10时说明到了最后一页,如果最后一页数据还是10,也不用担心,只要再次请求数据为0,则自动结束该请求 } } } //...此处省略 ``` * getDynamicList 获取动态列表 因为是请求小说类型,所以实际应该是getDynamicList_novel,参考资源类型表、合集类型表、用户类型表 * 假如有一个小说网站所有小说列表页:https://www.book.com/all?page=页码&sort=排序方式, 其HTML源代码如下: ```html 测试小说网所有小说列表 ``` ```javascript //...此处省略 "getDynamicList_novel": { "label": "小说动态列表", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl//填写的herf域名 } = params return baseUrl + '/all' }, "params": function(context, params) { const { currentPage,//页码 sort//排序方式 } = params return { page: currentPage, sort: sort == 'newest' ? 'new' : sort == 'hottest' ? 'hot' : sort == 'most' ? 'best' : 'new' } }, "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { HTMLparser, Single } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let box = document.getElementsByClassName('box')[0]//获取class为box的所有html标签及其子内容 let aa = new HTMLparser(box['innerHTML'].tirm()).getElementsByTagName('a') aa.forEach(a => { let adoc = new HTMLparser(a['innerHTML'].tirm()) let img = adoc.getElementsByClassName('cover')[0] let p = adoc.getElementsByClassName('desc')[0] let span = adoc.getElementsByClassName('author')[0] list[list.length-1].list.push( new Single({ singleId: a.attributes.href.replace('/book/', ''), title: a.attributes.title,//标题 cover: baseUrl + img.attributes.src,//封面 creator: span['innerHTML'].trim(),//作者 desc: p['innerHTML'].trim(),//简介 type: 'novel',//小说类型 source: source//填入该小说的来源 }) ) }) return { list: list,//返回list isLastPage: list.length < 10//假设存在分页每页数据为10,则当数据数量小于10时说明到了最后一页,如果最后一页数据还是10,也不用担心,只要再次请求数据为0,则自动结束该请求 } } } //...此处省略 ``` * search 搜索列表 因为是请求小说类型,所以实际应该是search_novel,参考资源类型表、合集类型表、用户类型表 * 假如有一个小说网站搜索列表页:https://www.book.com/search?page=页码&keyword=关键词&sort=排序方式,并且该页面格式为GBK,其HTML源代码如下: ```html 测试小说网所有小说列表 ``` ```javascript //...此处省略 "search_novel": { "label": "搜索小说列表", "charset": "gbk", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl//填写的herf域名 } = params return baseUrl + '/search' }, "params": function(context, params) { const { currentPage,//页码 sort,//排序方式 keyword//搜索词汇 } = params const { gb2312//utf-8字符转gbk字符 } = params return { page: currentPage, keyword: gb2312(keyword), sort: sort == 'newest' ? 'new' : sort == 'hottest' ? 'hot' : sort == 'most' ? 'best' : 'new' } }, "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { HTMLparser, Single } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let box = document.getElementsByClassName('box')[0]//获取class为box的所有html标签及其子内容 let aa = new HTMLparser(box['innerHTML'].tirm()).getElementsByTagName('a') aa.forEach(a => { let adoc = new HTMLparser(a['innerHTML'].tirm()) let img = adoc.getElementsByClassName('cover')[0] let p = adoc.getElementsByClassName('desc')[0] let span = adoc.getElementsByClassName('author')[0] list[list.length-1].list.push( new Single({ singleId: a.attributes.href.replace('/book/', ''), title: a.attributes.title,//标题 cover: baseUrl + img.attributes.src,//封面 creator: span['innerHTML'].trim(),//作者 desc: p['innerHTML'].trim(),//简介 type: 'novel',//小说类型 source: source//填入该小说的来源 }) ) }) return { list: list,//返回list isLastPage: list.length < 10//假设存在分页每页数据为10,则当数据数量小于10时说明到了最后一页,如果最后一页数据还是10,也不用担心,只要再次请求数据为0,则自动结束该请求 } } } //...此处省略 ``` * getKeyword 搜索关键词 因为是请求小说类型,所以实际应该是getKeyword_novel,参考来源类型表 * 假如有一个小说网站搜索关键词接口:https://www.book.com/api/getKeyword,其返回数据结构如下: ```javascript { "code": 1, "data": { "words": ['修仙', '爽文', '龙傲天', '系统', '穿越', '玄幻'] } } ``` ```javascript //...此处省略 "getKeyword_novel": { "label": "小说关键词", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl//填写的herf域名 } = params return baseUrl + '/api/getKeyword' }, "params": "", "headers": "", "value": function(context, params, res) { let list = [] if ( res.data.code == 1 ) { list = res.data.data.words } return { list: list,//返回list isLastPage: true//没有分页,直接返回true } } } //...此处省略 ``` * getFilterList 筛选列表 因为请求的时小说类型,所以实际应该是getFilterList_novel,参考资源类型表、合集类型表、用户类型表 * 假如有一个小说网站分页页:https://www.book.com/type,其HTML源代码如下: ```html 测试小说网分类列表 ``` ```javascript //...此处省略 "getFilterList_novel": { "label": "搜索小说列表", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl//填写的herf域名 } = params return baseUrl + '/type' }, "params": "", "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { HTMLparser } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let box = document.getElementsByClassName('box')[0]//获取class为box的所有html标签及其子内容 let aa = new HTMLparser(box['innerHTML'].tirm()).getElementsByTagName('a') aa.forEach(a => { list.push({ value: a.attributes.href.replace('/type/', ''), label: a['innerHTML'].trim(),//标题 source: source//填入该小说的来源 }) }) return { list: list,//返回list isLastPage: true//没有分页,直接返回true } } } //...此处省略 ``` * getFilterDetail 筛选详情 因为是请求小说类型,所以实际应该是getFilterDetail_novel,参考资源类型表、合集类型表、用户类型表 * 假如有一个小说网站分类详情页:https://www.book.com/type/分类ID/?page=页码&sort=排序方式, 其HTML源代码如下: ```html 测试小说网穿越小说 ``` ```javascript //...此处省略 "getFilterDetail_novel": { "label": "小说动态列表", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl,//填写的herf域名 value } = params return baseUrl + '/type/' + value }, "params": function(context, params) { const { currentPage,//页码 sort//排序方式 } = params return { page: currentPage, sort: sort == 'newest' ? 'new' : sort == 'hottest' ? 'hot' : sort == 'most' ? 'best' : 'new' } }, "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { HTMLparser, Single } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let box = document.getElementsByClassName('box')[0]//获取class为box的所有html标签及其子内容 let aa = new HTMLparser(box['innerHTML'].tirm()).getElementsByTagName('a') aa.forEach(a => { let adoc = new HTMLparser(a['innerHTML'].tirm()) let img = adoc.getElementsByClassName('cover')[0] let p = adoc.getElementsByClassName('desc')[0] let span = adoc.getElementsByClassName('author')[0] list[list.length-1].list.push( new Single({ singleId: a.attributes.href.replace('/book/', ''), title: a.attributes.title,//标题 cover: baseUrl + img.attributes.src,//封面 creator: span['innerHTML'].trim(),//作者 desc: p['innerHTML'].trim(),//简介 type: 'novel',//小说类型 source: source//填入该小说的来源 }) ) }) return { list: list,//返回list isLastPage: list.length < 10//假设存在分页每页数据为10,则当数据数量小于10时说明到了最后一页,如果最后一页数据还是10,也不用担心,只要再次请求数据为0,则自动结束该请求 } } } //...此处省略 ``` * getCharacterDetail 用户详情 假设用户类型为写手,所以实际应该是getCharacterDetail_writer,参考 用户类型表 * 假如有一个网站小说用户信息页:https://www.book.com/user/用户ID, 其HTML源代码如下: ```html 用户信息

小人当道

这个人很懒。什么都没留下 粉丝:120 关注:10
``` ```javascript //...此处省略 "getCharacterDetail_writer": { "label": "写手详情", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl,//填写的herf域名 characterId//用户ID } = params return baseUrl + '/user/' + characterId }, "params": "", "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { HTMLparser } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let info = document.getElementById('userInfo')//获取id为userInfo的所有html标签及其子内容 let infodoc = new HTMLparser(info['innerHTML'].tirm()) let name = infodoc.getElementsByClassName('name')[0]//获取用户姓名 let avatar = infodoc.getElementsByClassName('avatar')[0]//获取用户头像 let desc = infodoc.getElementsByClassName('desc')[0]//获取用户简介 let follower = infodoc.getElementsByClassName('follower')[0]//获取用户粉丝数 let followee = infodoc.getElementsByClassName('followee')[0]//获取用户关注数 return { data: {//这个data的属性与请求方法有关,比如请求为getCharacterDetail,则返回Character类中的属性,有值就传,没有就不传 name: name['innerHTML'].trim(), avatar: baseUrl + avatar.attributes.src, desc: desc['innerHTML'].trim(), follower: follower['innerHTML'].trim().replace('粉丝:', ''), followee: followee['innerHTML'].trim().replace('粉丝:', '') }//返回对象 } } } //...此处省略 ``` * getCharacterWorksList 用户作品列表 假设请求写手的小说作品,所以实际应该是getCharacterWorksList_writer_novel,参考 资源类型表、合集类型表 * 假如有一个查询用户小说作品接口:https://www.book.com/api/getNovel?user=用户ID&cursor=后台返回参数, 其数据结构如下: ```javascript { "code": 1, "data": { "cursor": '1231231',//下一页所需参数 "list": [{ "id": '15155', "title": '穿越到明朝', "cover": 'https://image.book.com/upload/4545.png', "author": '小人当道', "desc": '我穿越到了明朝' },{ "id": '15155', "title": '穿越到明朝', "cover": 'https://image.book.com/upload/4545.png', "author": '小人当道', "desc": '我穿越到了明朝' }] } } ``` ```javascript //...此处省略 "getCharacterWorksList_writer_novel": { "label": "写手小说列表", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl//填写的herf域名 } = params return baseUrl + '/api/getNovel' }, "params": function(context, params) { const { baseUrl,//填写的herf域名 characterId,//用户ID paging//分页信息 } = params return { user: characterId, cursor: paging.cursor || ''//第一次请求可以不传 } }, "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { Single } = context let list = [] if ( res.data.code == 1 ) { res.data.data.list.forEach(item => { list.push( new Single({ singleId: item.id, title: item.title, cover: item.cover, desc: item.desc, creator: item.author, type: 'novel', source: source }) ) }) } return { list: list,//返回小说列表 isLastPage: list.length < 10,//假设存在分页每页数据为10,则当数据数量小于10时说明到了最后一页,如果最后一页数据还是10,也不用担心,只要再次请求数据为0,则自动结束该请求 paging: {//返回分页信息 cursor: res.data.data.cursor || ''//返货下一页参数 } } } } //...此处省略 ``` * getCharacterFollowerList 用户粉丝列表 假设请求用户类型为写手,所以实际应该是getCharacterFollowerList_writer,参考 用户类型表 * 假如有一个查询用户粉丝列表接口:https://www.book.com/api/getFollower?user=用户ID&cursor=后台返回参数, 其数据结构如下: ```javascript { "code": 1, "data": { "cursor": '1231231',//下一页所需参数 "list": [{ "id": '15155', "name": '小人当道', "avatar": 'https://image.book.com/upload/4545.png', "desc": '这个人很懒。什么都没有留下' },{ "id": '15155', "name": '小人当道', "avatar": 'https://image.book.com/upload/4545.png', "desc": '这个人很懒。什么都没有留下' }] } } ``` ```javascript //...此处省略 "getCharacterFollowerList_writer": { "label": "写手粉丝列表", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl//填写的herf域名 } = params return baseUrl + '/api/getFollower' }, "params": function(context, params) { const { baseUrl,//填写的herf域名 characterId,//用户ID paging//分页信息 } = params return { user: characterId, cursor: paging.cursor || ''//第一次请求可以不传 } }, "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { Character } = context let list = [] if ( res.data.code == 1 ) { res.data.data.list.forEach(item => { list.push( new Character({ characterId: item.id, name: item.name, avatar: item.avatar, desc: item.desc, type: 'writer',//一般粉丝和用户的类型是一样的,如果不同,你可以自己更改类型 source: source }) ) }) } return { list: list,//返回小说列表 isLastPage: list.length < 10,//假设存在分页每页数据为10,则当数据数量小于10时说明到了最后一页,如果最后一页数据还是10,也不用担心,只要再次请求数据为0,则自动结束该请求 paging: {//返回分页信息 cursor: res.data.data.cursor || ''//返货下一页参数 } } } } //...此处省略 ``` * getCharacterFolloweeList 用户关注列表 假设请求用户类型为写手,所以实际应该是getCharacterFolloweeList_writer,参考 用户类型表 * 假如有一个查询用户关注列表接口:https://www.book.com/api/getFollowee?user=用户ID&cursor=后台返回参数, 其数据结构如下: ```javascript { "code": 1, "data": { "cursor": '1231231',//下一页所需参数 "list": [{ "id": '15155', "name": '小人当道', "avatar": 'https://image.book.com/upload/4545.png', "desc": '这个人很懒。什么都没有留下' },{ "id": '15155', "name": '小人当道', "avatar": 'https://image.book.com/upload/4545.png', "desc": '这个人很懒。什么都没有留下' }] } } ``` ```javascript //...此处省略 "getCharacterFolloweeList_writer": { "label": "写手关注列表", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl//填写的herf域名 } = params return baseUrl + '/api/getFollowee' }, "params": function(context, params) { const { baseUrl,//填写的herf域名 characterId,//用户ID paging//分页信息 } = params return { user: characterId, cursor: paging.cursor || ''//第一次请求可以不传 } }, "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { Character } = context let list = [] if ( res.data.code == 1 ) { res.data.data.list.forEach(item => { list.push( new Character({ characterId: item.id, name: item.name, avatar: item.avatar, desc: item.desc, type: 'writer',//一般关注人和用户的类型是一样的,如果不同,你可以自己更改类型 source: source }) ) }) } return { list: list,//返回小说列表 isLastPage: list.length < 10,//假设存在分页每页数据为10,则当数据数量小于10时说明到了最后一页,如果最后一页数据还是10,也不用担心,只要再次请求数据为0,则自动结束该请求 paging: {//返回分页信息 cursor: res.data.data.cursor || ''//返货下一页参数 } } } } //...此处省略 ``` * getSingleDetail 资源详情 因为是请求小说类型,所以实际应该是getSingleDetail_novel,参考 资源类型表 * 假如有一个网站小说详情页:https://www.book.com/book/小说ID, 其HTML源代码如下: ```html 穿越到明朝

穿越到明朝

穿越到明朝那些事 小人当道 2022-2-15 15415
``` ```javascript //...此处省略 "getSingleDetail_novel": { "label": "小说详情", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl,//填写的herf域名 singleId } = params return baseUrl + '/type/singleId' }, "params": "", "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { HTMLparser, Section, Character, getTag,//获取关键词 userAvatar//自定义方法 } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let info = document.getElementById('bookInfo')//获取id为bookInfo的所有html标签及其子内容 let infodoc = new HTMLparser(info['innerHTML'].tirm()) let title = infodoc.getElementsByClassName('title')[0]//获取小说标题 let cover = infodoc.getElementsByClassName('cover')[0]//获取小说封面 let desc = infodoc.getElementsByClassName('desc')[0]//获取小说简介 let updateTime = infodoc.getElementsByClassName('updateTime')[0]//获取小说更新时间 let readnum = infodoc.getElementsByClassName('readnum')[0]//获取小说阅读量 let author = infodoc.getElementsByClassName('author')[0]//获取作者信息 let character = new Character({//生成作者 characterId: author.attributes.href.replace('/author/', ''), name: author['innerHTML'].trim(), avatar: userAvatar(author.attributes.href.replace('/author/', '')), type: 'writer', source: source }) let sections = [] let chapter = document.getElementById('chapters') let aa = new HTMLparser(chapter['innerHTML'].tirm()).getElementsByTagName('a') let tag = getTag('novel', title['innerHTML'].trim() + '_' + author['innerHTML'].trim() + '_' + desc['innerHTML'].trim())//匹配该小说的标签列表,参考来源类型表 aa.forEach((a, key)=> { sections.push({ sectionId: a.attributes.href,//分段ID chapter: key + 1,//章节序号 小说的分段必加 title: a['innerHTML'].trim(),//标题 isStart: key == 0,//是否第一个章节 小说的分段必加 isEnd: key == aa.length-1,//是否最后一个章节 小说的分段必加 isPay: a.attributes.class == 'lock',//是否付费章节 type: 'novel',//类型 source: source }) }) return { data: {//这个data的属性与请求方法有关,比如请求为getSingleDetail,则返回single类中的属性,有值就传,没有就不传 commentId: params.singleId,//评论ID,注意,如果该网站具有评论功能,想要查看评论,必须填入commentId,就算查询评论所需要的ID和资源的ID一样也必须传 title: title['innerHTML'].trim(),//标题 cover: baseUrl + cover.attributes.src,//封面 desc: desc['innerHTML'].trim(),//简介 updateTime: updateTime['innerHTML'].trim(),//更新时间 readnum: readnum['innerHTML'].trim(),//阅读量 tag: tag,//标签列表 characters: [character]//返回作者列表 },//返回对象 sections: sections//小说章节列表 } } } //...此处省略 ``` * getSectionDetail 资源分段详情 因为是请求小说类型,所以实际应该是getSectionDetail_novel,参考 资源类型表 * 该请求方法根据类型不同,返回数据也不同,类型为小说、漫画,视频、壁纸时为请求分段详情,返回data对象,类型为文章、资讯、话题时作为分页请求,返回list数组,为音频、直播时该方法无效 * 假如有一个网站小说阅读页:https://www.book.com/book/小说ID/章节ID, 其HTML源代码如下: ```html 穿越到明朝

第一章 我穿越了

一觉醒来,我竟然穿越到了明朝

一觉醒来,我竟然穿越到了明朝

一觉醒来,我竟然穿越到了明朝

一觉醒来,我竟然穿越到了明朝

一觉醒来,我竟然穿越到了明朝

``` ```javascript //...此处省略 "getSectionDetail_novel": { "label": "章节内容", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl,//填写的herf域名 sectionId } = params return baseUrl + sectionId }, "params": "", "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { HTMLparser, htmlDecodeByRegExp } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let content = document.getElementById('bookContent')//获取id为bookContent的所有html标签及其子内容 return { data: {//这个data的属性与请求方法有关,比如请求为getSectionDetail,则返回Section类中的属性,有值就传,没有就不传 content: htmlDecodeByRegExp(content['innerHTML'].trim()),//注意小说内容支持纯文本模式 比如'内容内容内容内容内容内容/r/n内容内容内容内容内容内容' }//返回对象 } } } //...此处省略 ``` * getRecome 资源推荐 传入一个资源,获取其它相关资源 因为是请求小说类型,所以实际应该是getRecome_novel,参考 资源类型表、合集类型表、用户类型表 * 假如有一个网站小说详情页:https://www.book.com/book/小说ID, 其HTML源代码如下: ```html 穿越到明朝
穿越到明朝 穿越到明朝 穿越到明朝
``` ```javascript //...此处省略 "getRecome_novel": { "label": "小说推荐", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl,//填写的herf域名 singleId } = params return baseUrl + '/book/' + singleId }, "params": "", "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { HTMLparser, Single } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let other = document.getElementByClassName('other')[0]//获取class为other的所有html标签及其子内容 let books = new HTMLparser(other['innerHTML'].tirm()).getElementByClassName('book') books.forEach(book => { list.push( new Single({ singleId: book.attributes.href.replace('/book/', ''), title: book['innerHTML'].trim(), type: 'novel', source: source }) ) }) return { list: list,//返回推荐列表 isLastPage: true//没有分页,直接返回true } } } //...此处省略 ``` * getComment 评论列表 假设请求类型为小说,所以实际应该是getComment_novel,参考 资源类型表、合集类型表 * 假如有一个查询用户关注列表接口:https://www.book.com/api/getComment?id=用户ID&page=页码, 其数据结构如下: ```javascript { "code": 1, "data": { "list": [{ "id": '11155', "user": '我是坏人', "avatar": 'https://image.book.com/upload/4545.png', "time": '2022-12-21 12:39', "content": '好看加油', "subComment": [{ "id": '15125', "user": '我是好人', "avatar": 'https://image.book.com/upload/4545.png', "time": '2022-12-21 12:39', "content": '同感,加油!!!' }] },{ "id": '11155', "user": '小人当道', "avatar": 'https://image.book.com/upload/4545.png', "time": '2022-12-21 12:39', "content": '谢谢打赏', }] } } ``` ```javascript //...此处省略 "getComment_novel": { "label": "小说评论列表", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl//填写的herf域名 } = params return baseUrl + '/api/getComment' }, "params": function(context, params) { const { baseUrl,//填写的herf域名 commentId,//评论ID currentPage//页码 } = params return { id: commentId, page: currentPage } }, "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { Comment } = context let list = [] if ( res.data.code == 1 ) { res.data.data.list.forEach(item => { let subComments = [] if ( item.subComment ) { item.subComment.forEach(comment => { subComments.push( new Comment({ commentId: comment.id, title: comment.user, avatar: comment.avatar, content: comment.content, updateTime: comment.time, source: source }) ) }) } list.push( new Comment({ commentId: item.id, title: item.user, avatar: item.avatar, content: item.content, updateTime: item.time, subComment: subComments, source: source }) ) }) } return { list: list,//返回小说列表 isLastPage: list.length < 10//假设存在分页每页数据为10,则当数据数量小于10时说明到了最后一页,如果最后一页数据还是10,也不用担心,只要再次请求数据为0,则自动结束该请求 } } } //...此处省略 ``` #WebSocket * getSocketDetail WebSocket信息 目前该方法仅支持直播类型,所以实际是 getSocketDetail_live * 假如有一个直播网站的弹幕wss链接获取接口:https://www.live.com/api/getWebSocket?liveStreamId=直播ID, 其数据结构如下: ```javascript { "code": 1, "data": { websocketUrl: 'wss://www.live.com/grouo-123131',//wss 链接 send: 'liveStream:121212',//首次发送消息 heartbeat: 'liveStream:121212',//心跳任务参数 heartbeattime: 2000//心跳任务间隔 单位ms } } ``` ```javascript //...此处省略 "getSocketDetail_live": { "label": "获取WebScoket信息", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl//填写的herf域名 } = params return baseUrl + '/api/getWebSocket' }, "params": function(context, params) { const { singleId//直播间ID } = params return{ liveStreamId: singleId } }, "headers": "", "value": function(context, params, res) { let list = [] return { data: {//WebSocket配置,具体参考 官方的uni.connectSocket方法 url: res.data.data.websocketUrl }, send: res.data.send,//第一次发送消息 WebSocket连接成功后,发送一次消息,不传则不发 heartbeat: res.data.heartbeat,//心跳任务消息 WebSocket连接成功后,开始心跳任务,不传则没有心跳任务 heartbeattime: res.data.heartbeattime//心跳任务间隔时间 单位为ms } } } //...此处省略 ``` * handleSocketMessage 处理WebSocket接收到的消息 目前该方法仅支持处理直播弹幕 * 假如有一个WebSocket接收到的消息数据结构如下: ```javascript { key: 'das89da9s8d9ad', user: '我是好人',//消息发送人 content: '不错不错',//消息内容 color: '#ff033',//消息内容颜色 type: 'user'//用户发送消息 } ``` ```javascript //...此处省略 "handleSocketMessage": { "label": "处理WebScoket消息", "charset": "utf8", "method": "none",//因为不访问线上接口,直接选择none "interval": 0, "url": "", "params": "", "headers": "", "value": function(context, params) {//没有访问线上接口,没有res参数 const { baseUrl, source } = params const { Barrage } = context let list = [] list.push( new Barrage({ id: params.key + '_' + source, text: params.content,//消息内容 color: params.color,//消息颜色 name: params.user,//发送人 type: params.type,//消息类型 source: source }) ) return { barrages: list//不关有多少条消息,只返回数组 } } } //...此处省略 ``` #文章、资讯和社区的getSectionDetail * 这三种类型的getSectionDetail和其它类型不同,他们不存在Section类的分段内容,该方法在此表现为分页请求 * 假如有一个社区帖子详情页面为:https://www.forum.com/bbs/帖子ID?page=页码, 其HTML源代码如下: ```html 今年怎么样 ``` ```javascript //...此处省略 "getSectionDetail_talk": { "label": "话题内容", "charset": "utf8", "method": "get", "interval": 0, "url": function(context, params) { const { baseUrl,//填写的herf域名 singleId } = params return baseUrl + '/bbs/' + singleId }, "params": function(context, params) { const { currentPage } = params return { page: currentPage } }, "headers": "", "value": function(context, params, res) { const { baseUrl, source } = params const { Single } = context let list = [] let document = new HTMLparser(res.data.tirm())//res.data 为 请求到的网页源代码 如果请求的为api接口 则为JSON数据 let contaier = document.getElementsByClassName('contaier')[0]//获取class为contaier的所有html标签及其子内容 let lis = new HTMLparser(contaier['innerHTML'].tirm()).getElementsByTagName('li')//获取所有li标签及其子内容 lis.forEach(li => { let lidoc = new HTMLparser(li['innerHTML'].tirm()) let name = lidoc.getElementsByClassName('name')[0] let avatar = lidoc.getElementsByClassName('avatar')[0] let updateTime = lidoc.getElementsByClassName('updateTime')[0] let content = lidoc.getElementsByClassName('content')[0] list.push( new Single({ singleId: li.attributes['data-id'], avatar: baseUrl + avatar.attributes.src,//头像 creator: name['innerHTML'].trim(),//发布人 updateTime: updateTime['innerHTML'].trim(),//发布时间 content: content['innerHTML'].trim(),//内容 type: 'talk',//话题类型 source: source }) ) }) return { list: list,//返回小说列表 isLastPage: list.length < 10//假设存在分页每页数据为10,则当数据数量小于10时说明到了最后一页,如果最后一页数据还是10,也不用担心,只要再次请求数据为0,则自动结束该请求 } } } //...此处省略 ```