原作者: Celeter
现作者: 喵公子
更新时间: 2024-02-27
描述: 本说明是legado的规则说明,禁止其他未获得本人授权的第三方软件使用
JSOUP之Default
xxxxxxxxxx
▲ @为分隔符,用来分隔获取规则
·每段规则可分为3段
·第一段是类型,如class,id,tag,text,children等, children获取所有子标签,不需要第二段和第三段,text可以根据文本内容获取
·第二段是名称,text. 第二段为文本内容的一部分
·第三段是位置,class,tag,id等会获取到多个,所以要加位置
·如不加位置会获取所有
·位置正着数从0开始,0是第一个,如为负数则是取倒着数的值,-1为倒数第一个,-2为倒数第二个
·!是排除,有些位置不符合需要排除用!,后面的序号用:隔开0是第1个,负数为倒数序号,-1最后一个,-2倒数第2个,依次
·获取列表的最前面加上负号- 可以使列表倒置,有些网站目录列表是倒的,前面加个负号可变为正的
·@的最后一段为获取内容,如text,textNodes,ownText,href,src,html,all等
·如需要正则替换在最后加上 ##正则表达式##替换内容,替换内容为空时,第二个##可以省略
·例:class.odd.0@tag.a.0@text||tag.dd.0@tag.h1@text##全文阅读
·例:class.odd.0@tag.a.0@text&&tag.dd.0@tag.h1@text##全文阅读
▲ 增加支持类似数组的写法
·格式如:[index,index, ...]或[!index,index, ...],其中[!`开头表示筛选方式为排除,index可以是单个索引,也可以是区间
·区间格式为[start:end]或[start:end:step],其中start为0时可省略,end为-1时可省略
·索引(index)、区间两端(start和end)、区间间隔(step)都支持负数
·特殊用法tag.div[-1:0],可在任意地方让列表反向
▲ 允许索引作为@分段后每个部分的首规则,此时相当于前面是children
·head@.1@text与head@[1]@text与head@children[1]@text等价
JSOUP之CSS
@css:
开头JSONPath
@json:
或 $.
开头,其他形式不可靠XPath
@XPath:
或 //
开头JavaScript
<js></js>
、@js:
中使用,结果存在result中@js:
只能放在其他规则的最后使用<js></js>
可以在任意位置使用,还能作为其他规则的分隔符,例:tag.li<js></js>//a
+
开头,使用AllInOne规则正则之AllInOne
正则之OnlyOne
##正则表达式##替换内容###
正则之净化
##正则表达式##替换内容
all##正则表达式##替换内容
自定义三种连接符号
符号:&&
、||
、%%
只能在同种规则间使用,不包括js和正则
&&
会合并所有取到的值,
||
会以第一个取到值的为准
%%
会依次取数,如三个列表,
先取列表1的第一个,再取列表2的第一个,再取列表3的第一个,
再取列表1的第二个,再取列表2的第二个...
URL必知必会
请求头
一般形式,如下所示
xxxxxxxxxx
{
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36",
"Accept-Language":"zh-CN,zh;q=0.9"
}
复杂情况可使用js
xxxxxxxxxx
(()=>{
var ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36";
var headers = {"User-Agent": ua};
return JSON.stringify(headers);
})()
※其中,ua
必须保证是JavaScript
的String
类型,JSON.stringify()
才能将header
转换为字符串。
获取登录后的cookie
xxxxxxxxxx
java.getCookie("http://baidu.com", null) => userid=1234;pwd=adbcd
java.getCookie("http://baidu.com", "userid") => 1234
请求头中支持http代理,socks4 socks5代理设置
xxxxxxxxxx
// socks5代理
{
"proxy":"socks5://127.0.0.1:1080"
}
// http代理
{
"proxy":"http://127.0.0.1:1080"
}
// 支持代理服务器验证
{
"proxy":"socks5://127.0.0.1:1080@用户名@密码"
}
// 注意:这些请求头是无意义的,会被忽略掉
GET请求
一般形式如下,charset为utf-8时可省略,无特殊情况不需要请求头和webView,参数webView非空时采用webView加载
xxxxxxxxxx
https://www.baidu.com,{
"charset": "gbk",
"headers": {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"},
"webView": true
}
复杂情况可使用js
xxxxxxxxxx
var ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36";
var headers = {"User-Agent": ua};
var option = {
"charset": "gbk",
"headers": headers,
"webView": true
};
"https://www.baidu.com," + JSON.stringify(option)
POST请求
一般形式如下,body是请求体,charset为utf-8时可省略,无特殊情况不需要请求头和webView,参数webView非空时采用webView加载
xxxxxxxxxx
https://www.baidu.com,{
"charset": "gbk",
"method": "POST",
"body": "bid=10086",
"headers": {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"},
"webView": true
}
复杂情况可使用js
xxxxxxxxxx
var ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36";
var headers = {"User-Agent": ua};
var body = "bid="+"10086";
var option = {
"charset": "gbk",
"method": "POST",
"body": String(body),
"headers": headers,
"webView": true
};
"https://www.baidu.com," + JSON.stringify(option)
※其中,body
必须保证是JavaScript
的String
类型,变量是计算得到的尽量都用String()
强转一下类型。
变量的put与get
@put
与@get
只能用于js以外的规则中,@put里使用JSONPath不需要加引号,其他规则需要加引号,
例:@put:{bid:"//*[@bid-data]/@bid-data"}
java.put
与java.get
只能用于js中,在js中无法使用@get
{{}}
与{}
规则
在搜索URL与发现URL中的{{}}
在{{}}里只能使用js
在搜索URL与发现URL以外的{{}}
可在{{}}
中使用任意规则(正则除外?),默认为js,使用其他规则需要有明显的标志头,
如:Default规则需要以@@
开头,XPath需要以@xpath:
或//
开头,JSONPath需要以@json:
或$.
开头,CSS需要以@css:
开头
{}
规则
留用了阅读2.0的规则,只能使用JSONPath,尽量避免使用
自定义js
在js中调用java的常规方法:由于java这个关键字已经被使用,调用java开头的包名时需使用全局变量Packages 参考脚本之家
io.legado.app.utils.htmlFormat(str)
、org.jsoup.Jsoup.parse(str)
with
的范围内,其内使用java相关语法,最后在作用域外被js调用了作用域内的函数xxxxxxxxxx
var javaImport = new JavaImporter();
javaImport.importPackage(
Packages.java.lang,
Packages.java.security
);
with(javaImport){
function strToMd5By32(str) {
var reStr = null;
var md5 = MessageDigest.getInstance("MD5");
var bytes = md5.digest(String(str).getBytes());
var stringBuffer = new StringBuilder();
bytes.forEach(a=>{
var bt = a & 0xff;
if (bt < 16) {
stringBuffer.append("0");
}
stringBuffer.append(Integer.toHexString(bt));
});
reStr = stringBuffer.toString();
return reStr;
}
}
strToMd5By32('123')
变量
xxxxxxxxxx
baseUrl // 变量-当前url,String
result // 变量-上一步的结果
book // 变量-书籍类,方法见 io.legado.app.data.entities.Book
cookie // 变量-cookie操作类,方法见 io.legado.app.help.http.CookieStore
cache // 变量-缓存操作类,方法见 io.legado.app.help.CacheManager
chapter // 变量-当前目录类,方法见 io.legado.app.data.entities.BookChapter
title // 变量-当前标题,String
src // 内容,源码
下面是一些常用的函数,详见JsExtensions.kt
x//访问网络,urlStr为url字符串,返回类型String?
java.ajax(urlStr: String)
//并发访问网络,urlList为url数组,返回StrResponse?的数组,若要获取body,需使用.body()
java.ajaxAll(urlList: Array<String>): Array<StrResponse?>
//访问网络,urlStr为url字符串,返回Response<String>,已废弃
java.connect(urlStr: String)
//文件下载,content为十六进制字符串,url用于生成文件名,返回String文件相对路径
java.downloadFile(content: String, url: String)
//实现重定向拦截,返回[Connection.Response](https://jsoup.org/apidocs/org/jsoup/Connection.Response.html)
java.get(url: String, headers: Map<String, String>)
java.post(urlStr: String, body: String, headers: Map<String, String>)
//实现cookie读取,返回String
java.getCookie(tag: String, key: String?)
//base64解码,返回类型String
java.base64Decode(str: String)
java.base64Decode(str: String, flags: Int)
//base64解码,返回类型ByteArray?
java.base64DecodeToByteArray(str: String?)
java.base64DecodeToByteArray(str: String?, flags: Int)
//base64编码,返回类型String?
java.base64Encode(str: String)
java.base64Encode(str: String, flags: Int)
//md5编码,返回类型String?
java.md5Encode(str: String)
java.md5Encode16(str: String)
//格式化时间戳,返回类型String
java.timeFormat(timestamp: Long)
java.timeFormat(time: String)
//utf8编码转gbk编码,返回String
java.utf8ToGbk(str: String)
//实现字符串的URI编码,enc为编码格式,返回String
java.encodeURI(str: String) //默认enc="UTF-8"
java.encodeURI(str: String, enc: String)
//html格式化,返回String
java.htmlFormat(str: String)
//获取本地文件,path为文件的相对路径,返回File
java.getFile(path: String)
//读取本地文件,返回ByteArray?
java.readFile(path: String)
//读取本地文本文件,charsetName为编码格式
java.readTxtFile(path: String) //自动识别charsetName不一定准,乱码时请手动指定
java.readTxtFile(path: String, charsetName: String)
//删除文件或文件夹
deleteFile(path: String)
//zip文件解压,zipPath为压缩文件路径,返回String解压相对路径,会删除原文件只保留解压后的文件
java.unzipFile(zipPath: String)
//文件夹内所有文本文件读取,返回内容String,会删除文件夹
java.getTxtInFolder(unzipPath: String)
//获取网络zip文件中的数据,url为zip文件链接,path为所需获取文件在zip内的路径,返回文件数据String
java.getZipStringContent(url: String, path: String)
//获取网络zip文件中的数据,url为zip文件链接,path为所需获取文件在zip内的路径,返回文件数据ByteArray?
java.getZipByteArrayContent(url: String, path: String)
//解析字体,返回字体解析类QueryTTF?
java.queryBase64TTF(base64: String?)
//str支持url,本地文件,base64,自动判断,自动缓存,返回字体解析类QueryTTF?
java.queryTTF(str: String?)
//text为包含错误字体的内容,font1为错误的字体,font2为正确的字体,返回字体对应的字
java.replaceFont(text: String,font1: QueryTTF?,font2: QueryTTF?)
//输出调试日志
java.log(msg: String)
//AES解码为ByteArray?,str为传入的AES加密数据,key为AES解密key,transformation为AES加密方式,iv为ECB模式的偏移向量
java.aesDecodeToByteArray(str: String, key: String, transformation: String, iv: String)
//AES解码为String?,str为传入的AES加密数据,key为AES解密key,transformation为AES加密方式,iv为ECB模式的偏移向量
java.aesDecodeToString(str: String, key: String, transformation: String, iv: String)
//已经base64的AES解码为ByteArray?,str为Base64编码数据,key为AES解密key,transformation为AES加密方式,iv为ECB模式的偏移向量
java.aesBase64DecodeToByteArray(str: String, key: String, transformation: String, iv: String)
//已经base64的AES解码为String?,str为Base64编码数据,key为AES解密key,transformation为AES加密方式,iv为ECB模式的偏移向量
java.aesBase64DecodeToString(str: String, key: String, transformation: String, iv: String)
//加密aes为ByteArray?,data为传入的原始数据,key为AES解密key,transformation为AES加密方式,iv为ECB模式的偏移向量
java.aesEncodeToByteArray(data: String, key: String, transformation: String, iv: String)
//加密aes为String?,data为传入的原始数据,key为AES解密key,transformation为AES加密方式,iv为ECB模式的偏移向量
java.aesEncodeToString(data: String, key: String, transformation: String, iv: String)
//加密aes后Base64化的ByteArray?,data为传入的原始数据,key为AES解密key,transformation为AES加密方式,iv为ECB模式的偏移向量
java.aesEncodeToBase64ByteArray(data: String, key: String, transformation: String, iv: String)
//加密aes后Base64化的String?,data为传入的原始数据,key为AES解密key,transformation为AES加密方式,iv为ECB模式的偏移向量
java.aesEncodeToBase64String(data: String, key: String, transformation: String, iv: String)
/**************以下部分方法由于JAVA不支持参数默认值,调用时不能省略***************/
//设置需解析的内容content和baseUrl,返回类型AnalyzeRule
java.setContent(content: Any?, baseUrl: String? = this.baseUrl)
//输入规则rule和URL标志isUrl获取文本列表,返回类型List<String>?
java.getStringList(rule: String, isUrl: Boolean = false)
//输入规则rule和URL标志isUrl获取文本,返回类型String
java.getString(ruleStr: String?, isUrl: Boolean = false)
//输入规则ruleStr获取节点列表,返回类型List<Any>
java.getElements(ruleStr: String)
url添加js参数,解析url时执行,可在访问url时处理url,例:
xxxxxxxxxx
https://www.baidu.com,{"js":"java.headerMap.put('xxx', 'yyy')"}
https://www.baidu.com,{"js":"java.url=java.url+'yyyy'"}
url全部参数,详见AnalyzeUrl.kt
xxxxxxxxxx
data class UrlOption(
val method: String?,
val charset: String?,
val webView: Any?,
val headers: Any?,
val body: Any?,
val type: String?,
val js: String?,
val retry: Int = 0 //重试次数
)
书源URL(bookSourceUrl)
书源名称(bookSourceName)
书源分组(bookSourceGroup)
登录URL(loginUrl)
书籍URL正则(bookUrlPattern)
可不填
添加网址时,用于识别书源
xxxxxxxxxx
例:https?://www.piaotian.com/bookinfo/.*
请求头(header)
搜索地址(url)
key
为关键字标识,通常形态为{{key}}
,运行时会替换为搜索关键字
也可以对key进行加密等操作,如:{{java.base64Encode(key)}}
page
为关键字标识,通常形态为{{page}}
,page的初值为1也可以对page进行计算,
如:{{(page-1)*20}}
,有时会遇到第一页没有页数的情况,有两种方法:
① {{page - 1 == 0 ? "": page}}
② <,{{page}}>
支持相对URL
书籍列表规则(bookList)
书名规则(name)
作者规则(author)
分类规则(kind)
字数规则(wordCount)
最新章节规则(lastChapter)
简介规则(intro)
封面规则(coverUrl)
详情页url规则(bookUrl)
发现地址规则(url)
page
为关键字标识,通常形态为{{page}}
,page的初值为1,也可以对page进行计算,
如:{{(page-1)*20}}
,有时会遇到第一页没有页数的情况,有两种方法:
① {{page - 1 == 0 ? "": page}}
② <,{{page}}>
格式一,如: 名称::http://www。baidu.com
,发现URL可使用&&
或换行符\n
隔开
格式二,有5个样式属性(layout_flexGrow、layout_flexShrink、layout_alignSelf、layout_flexBasisPercent、layout_wrapBefore)需要了解,详情见简书,写法如:
xxxxxxxxxx
[
{
"title": "今日限免",
"url": "https://app-cdn.jjwxc.net/bookstore/getFullPage?channel=novelfree",
"style": {
"layout_flexGrow": 1
}
},
{
"title": "频道金榜",
"url": "http://app-cdn.jjwxc.net/bookstore/getFullPage?channelBody=%7B%229%22%3A%7B%22offset%22%3A%22<,{{(page-1)*25}}>%22%2C%22limit%22%3A%2225%22%7D%7D&versionCode=148",
"style": {
"layout_flexGrow": 0,
"layout_flexShrink": 1,
"layout_alignSelf": "auto",
"layout_flexBasisPercent": -1,
"layout_wrapBefore": true
}
},
{
"title": "幻想未来",
"url": "http://app-cdn.jjwxc.net/bookstore/getFullPage?channelBody=%7B%2222000023%22%3A%7B%22offset%22%3A%22<,{{(page-1)*25}}>%22%2C%22limit%22%3A%2225%22%7D%7D&versionCode=148"
}
]
支持相对URL
书籍列表规则(bookList)
书名规则(name)
作者规则(author)
分类规则(kind)
字数规则(wordCount)
最新章节规则(lastChapter)
简介规则(intro)
封面规则(coverUrl)
详情页url规则(bookUrl)
预处理规则(bookInfoInit)
只能使用正则之AllInOne或者js
正则之AllInOne必须以:
开头
js的返回值需要是json对象,例:
xxxxxxxxxx
(function(){
return {
a:"圣墟",
b:"辰东",
c:"玄幻",
d:"200万字",
e:"第两千章 辰东肾虚",
f:"在破败中崛起,在寂灭中复苏。沧海成尘,雷电枯竭...",
g:"https://bookcover.yuewen.com/qdbimg/349573/1004608738/300",
h:"https://m.qidian.com/book/1004608738"
};
})()
此时,书名规则填a
,作者规则填b
,分类规则填c
,字数规则填d
,最新章节规则填e
,简介规则f
,封面规则填g
,目录URL规则填h
书名规则(name)
作者规则(author)
分类规则(kind)
字数规则(wordCount)
最新章节规则(lastChapter)
简介规则(intro)
封面规则(coverUrl)
目录URL规则(tocUrl)
允许修改书名作者(canReName)
目录列表规则(chapterList)
-
)可使列表反序章节名称规则(ruleChapterName)
章节URL规则(chapterUrl)
VIP标识(isVip)
null
false
0
""
时为非VIP章节信息(ChapterInfo)
目录下一页规则(nextTocUrl)
[]
或 null
或 ""
时停止加载下一页正文规则(content)
正文图片链接支持修改headers
xxxxxxxxxx
let options = {
"headers": {"User-Agent": "xxxx","Referrer":baseUrl,"Cookie":"aaa=vbbb;"}
};
'<img src="'+src+","+JSON.stringify(options)+'">'
book对象的可用属性
{{}}
中使用book.属性
的方式即可获取,如在正文内容后加上##{{book.name+"正文卷"+title}}
可以净化 书名+正文卷+章节名称(如:我是大明星正文卷第二章我爸是豪门总裁) 这一类的字符xxxxxxxxxx
bookUrl // 详情页Url(本地书源存储完整文件路径)
tocUrl // 目录页Url (toc=table of Contents)
origin // 书源URL(默认BookType.local)
originName // 书源名称 or 本地书籍文件名
name // 书籍名称(书源获取)
author // 作者名称(书源获取)
kind // 分类信息(书源获取)
customTag // 分类信息(用户修改)
coverUrl // 封面Url(书源获取)
customCoverUrl // 封面Url(用户修改)
intro // 简介内容(书源获取)
customIntro // 简介内容(用户修改)
charset // 自定义字符集名称(仅适用于本地书籍)
type // 0:text 1:audio
group // 自定义分组索引号
latestChapterTitle // 最新章节标题
latestChapterTime // 最新章节标题更新时间
lastCheckTime // 最近一次更新书籍信息的时间
lastCheckCount // 最近一次发现新章节的数量
totalChapterNum // 书籍目录总数
durChapterTitle // 当前章节名称
durChapterIndex // 当前章节索引
durChapterPos // 当前阅读的进度(首行字符的索引位置)
durChapterTime // 最近一次阅读书籍的时间(打开正文的时间)
canUpdate // 刷新书架时更新书籍信息
order // 手动排序
originOrder //书源排序
variable // 自定义书籍变量信息(用于书源规则检索书籍信息)
chapter对象的可用属性
{{}}
中使用chapter.属性
的方式即可获取,如在正文内容后加上##{{chapter.title+chapter.index}}
可以净化 章节标题+序号(如 第二章 天仙下凡2) 这一类的字符xxxxxxxxxx
url // 章节地址
title // 章节标题
baseUrl // 用来拼接相对url
bookUrl // 书籍地址
index // 章节序号
resourceUrl // 音频真实URL
tag // 章节信息
start // 章节起始位置
end // 章节终止位置
variable // 变量
如下示例,在详情页(目录页)和正文使用webView加载,例:
xxxxxxxxxx
{
"bookSourceComment": "",
"bookSourceGroup": " 有声",
"bookSourceName": "猫耳FM",
"bookSourceType": 1,
"bookSourceUrl": "https://www.missevan.com",
"customOrder": 0,
"enabled": false,
"enabledExplore": true,
"lastUpdateTime": 0,
"ruleBookInfo": {},
"ruleContent": {
"content": "https://static.missevan.com/{{//*[contains(@class,\"pld-sound-active\")]/@data-soundurl64}}",
"sourceRegex": "",
"webJs": ""
},
"ruleExplore": {},
"ruleSearch": {
"author": "author",
"bookList": "$.info.Datas",
"bookUrl": "https://www.missevan.com/mdrama/drama/{{$.id}},{\"webView\":true}",
"coverUrl": "cover ",
"intro": "abstract",
"kind": "{{$.type_name}},{{$.catalog_name}}",
"lastChapter": "newest ",
"name": "name",
"wordCount": "catalog_name "
},
"ruleToc": {
"chapterList": "@css:.scroll-list.btn-groups>a",
"chapterName": "text",
"chapterUrl": "href##$##,{\"webView\":true}"
},
"searchUrl": "https://www.missevan.com/dramaapi/search?s={{key}}&page=1",
"weight": 0
}
正文下一页URL规则(nextContentUrl)
WebViewJs(webJs)
getDecode()
,使正文部分解密:xxxxxxxxxx
{
"bookSourceGroup": "阅读3.0书源合集",
"bookSourceName": "🔥斋书苑",
"bookSourceType": 0,
"bookSourceUrl": "https://www.zhaishuyuan.com",
"bookUrlPattern": "",
"customOrder": 11,
"enabled": false,
"enabledExplore": false,
"exploreUrl": "男生书库::/shuku/0_1_0_0_0_{{page}}_0_0\n男频连载::/shuku/0_2_0_0_0_{{page}}_0_0",
"lastUpdateTime": 0,
"loginUrl": "",
"ruleBookInfo": {
"author": "@css:[property=og:novel:author]@content",
"coverUrl": "@css:[property=og:image]@content",
"intro": "@css:#bookintro@html",
"kind": "@css:[property=og:novel:category]@content",
"lastChapter": "@css:[property=og:novel:latest_chapter_name]@content",
"name": "@css:[property=og:novel:book_name]@content",
"tocUrl": "@css:[property=og:novel:read_url]@content",
"wordCount": "@css:.count li:eq(3)>span@text"
},
"ruleContent": {
"content": "all",
"nextContentUrl": "",
"webJs": "getDecode();$('#content').html();"
},
"ruleExplore": {
"author": "//li[4]/a/text()",
"bookList": "//ul[count(../ul)>10]",
"bookUrl": "//li[3]/a/@href",
"coverUrl": "##/book/(\\d+)##https://img.zhaishuyuan.com/bookpic/s$1.jpg###",
"intro": "//li[6]/text()",
"kind": "//li[2]/text()##\\[|\\]",
"lastChapter": "//span/a/text()",
"name": "//li[3]/a/text()",
"wordCount": "//li[5]/text()"
},
"ruleSearch": {
"author": "//dd[2]/span[1]/text()",
"bookList": "//*[@id=\"sitembox\"]/dl",
"bookUrl": "//dt/a/@href",
"coverUrl": "//img/@_src",
"intro": "//dd[3]/html()",
"kind": "//dd[2]/span[3]/text()",
"lastChapter": "//dd[4]/a/text()",
"name": "//h3/a//text()",
"wordCount": "//dd[2]/span[4]/text()"
},
"ruleToc": {
"chapterList": ":href=\"(/chapter/[^\"]*)\"[^>]*>([^<]*)</a>([^<]*)",
"chapterName": "$2",
"chapterUrl": "$1,{\"webView\":true}",
"nextTocUrl": "//strong/following-sibling::a/@href",
"updateTime": "$3"
},
"searchUrl": "/search/,{\n \"charset\": \"gbk\",\n \"method\": \"POST\",\n \"body\": \"page={{page}}&key={{key}}\"\n}",
"weight": 0
}
资源正则(sourceRegex)
用于嗅探
一般情况下的无脑教程如下
,{"webView":true}
,不要洒敷敷的写成 tag.a@href,{"webView":true}
或$.link,{"webView":true}
,正确写法如:tag.a@href##$##{"webView":true}
,{{@@tag.a@href}},{"webView":true}
,tag.a@href@js:result+',{"webView":true}'
等千万别带,{"webView":true}
.*\.(mp3|mp4).*
这个就可以了<js>result</js>
如下示例,在正文嗅探mp3和mp4的资源:
xxxxxxxxxx
{
"bookSourceComment": "",
"bookSourceGroup": " 有声",
"bookSourceName": "猫耳FM",
"bookSourceType": 1,
"bookSourceUrl": "https://www.missevan.com",
"customOrder": 0,
"enabled": false,
"enabledExplore": true,
"lastUpdateTime": 0,
"ruleBookInfo": {},
"ruleContent": {
"content": "https://static.missevan.com/{{//*[contains(@class,\"pld-sound-active\")]/@data-soundurl64}}",
"sourceRegex": "",
"webJs": ""
},
"ruleExplore": {},
"ruleSearch": {
"author": "author",
"bookList": "$.info.Datas",
"bookUrl": "https://www.missevan.com/mdrama/drama/{{$.id}},{\"webView\":true}",
"coverUrl": "cover ",
"intro": "abstract",
"kind": "{{$.type_name}},{{$.catalog_name}}",
"lastChapter": "newest ",
"name": "name",
"wordCount": "catalog_name "
},
"ruleToc": {
"chapterList": "@css:.scroll-list.btn-groups>a",
"chapterName": "text",
"chapterUrl": "href##$##,{\"webView\":true}"
},
"searchUrl": "https://www.missevan.com/dramaapi/search?s={{key}}&page=1",
"weight": 0
}
显示js的报错信息
xxxxxxxxxx
(function(result){
try{
// 处理result
// ...
// 当返回结果为字符串时
return result;
// 当返回结果为列表时
return list;
}
catch(e){
// 当返回结果为字符串时
return ""+e;
// 当返回结果为列表时
return [""+e]; //列表对应名称处填<js>""+result</js>查看
}
})(result);
请善用调试功能
调试搜索
输入关键字,如:系统
调试发现
输入发现URL,如:月票榜::https://www.qidian.com/rank/yuepiao?page={{page}}
调试详情页
输入详情页URL,如:https://m.qidian.com/book/1015609210
调试目录页
输入目录页URL,如:++https://www.zhaishuyuan.com/read/30394
调试正文页
输入正文页URL,如:--https://www.zhaishuyuan.com/chapter/30394/20940996
无脑{"webView":true}
很方便
特别注意用JSON.stringify()
方法时,需要保证JSON对象的value都是JavaScript
的String
类型(在阅读3.0中)
附:
书源一
xxxxxxxxxx
{
"bookSourceComment": "",
"bookSourceGroup": "CSS; 正则",
"bookSourceName": "小说2016",
"bookSourceType": 0,
"bookSourceUrl": "https://www.xiaoshuo2016.com",
"bookUrlPattern": "",
"customOrder": 0,
"enabled": true,
"enabledExplore": false,
"exploreUrl": "",
"lastUpdateTime": 0,
"loginUrl": "",
"ruleBookInfo": {
"author": "##:author\"[^\"]+\"([^\"]*)##$1###",
"coverUrl": "##og:image\"[^\"]+\"([^\"]*)##$1###",
"intro": "##:description\"[^\"]+\"([\\w\\W]*?)\"/##$1###",
"kind": "##:category\"[^\"]+\"([^\"]*)##$1###",
"lastChapter": "##_chapter_name\"[^\"]+\"([^\"]*)##$1###",
"name": "##:book_name\"[^\"]+\"([^\"]*)##$1###",
"tocUrl": ""
},
"ruleContent": {
"content": "@css:.articleDiv p@textNodes##搜索.*手机访问|一秒记住.*|.*阅读下载|<!\\[CDATA\\[|\\]\\]>",
"nextContentUrl": ""
},
"ruleExplore": {},
"ruleSearch": {
"author": "@css:p:eq(2)>a@text",
"bookList": "@css:li.clearfix",
"bookUrl": "@css:.name>a@href",
"coverUrl": "@css:img@src",
"intro": "@css:.note.clearfix p@text",
"kind": "@css:.note_text,p:eq(4)@text",
"lastChapter": "@css:p:eq(3)@text",
"name": "@css:.name@text"
},
"ruleToc": {
"chapterList": "-:<li><a[^\"]+\"([^\"]*)\">([^<]*)",
"chapterName": "$2",
"chapterUrl": "$1",
"nextTocUrl": ""
},
"searchUrl": "/modules/article/search.php?searchkey={{key}}&submit=&page={{page}},{\n \"charset\": \"gbk\"\n}",
"weight": 0
}
书源二
xxxxxxxxxx
{
"bookSourceComment": "",
"bookSourceGroup": "XPath; 正则",
"bookSourceName": "采墨阁手机版",
"bookSourceType": 0,
"bookSourceUrl": "https://m.caimoge.com",
"bookUrlPattern": "",
"customOrder": 0,
"enabled": true,
"enabledExplore": false,
"exploreUrl": "",
"lastUpdateTime": 0,
"loginUrl": "",
"ruleBookInfo": {
"author": "//*[@property=\"og:novel:author\"]/@content",
"coverUrl": "//*[@property=\"og:image\"]/@content",
"intro": "//*[@property=\"og:description\"]/@content",
"kind": "//*[@property=\"og:novel:category\"]/@content",
"lastChapter": "//*[@id=\"newlist\"]//li[1]/a/text()",
"name": "//*[@property=\"og:novel:book_name\"]/@content",
"tocUrl": "//a[text()=\"阅读\"]/@href"
},
"ruleContent": {
"content": "//*[@id=\"content\"]",
"nextContentUrl": ""
},
"ruleExplore": {},
"ruleSearch": {
"author": "//dd[2]/text()",
"bookList": "//*[@id=\"sitebox\"]/dl",
"bookUrl": "//dt/a/@href",
"coverUrl": "//img/@src",
"kind": "//dd[2]/span/text()",
"lastChapter": "",
"name": "//h3/a/text()"
},
"ruleToc": {
"chapterList": ":href=\"(/read[^\"]*html)\">([^<]*)",
"chapterName": "$2",
"chapterUrl": "$1",
"nextTocUrl": "//*[@id=\"pagelist\"]/*[position()>1]/@value"
},
"searchUrl": "/search.html,{\n \"method\": \"POST\",\n \"body\": \"searchkey={{key}}\"\n}",
"weight": 0
}
书源三
xxxxxxxxxx
{
"bookSourceComment": "",
"bookSourceGroup": "JSon",
"bookSourceName": "猎鹰小说网",
"bookSourceType": 0,
"bookSourceUrl": "http://api.book.lieying.cn",
"customOrder": 0,
"enabled": true,
"enabledExplore": false,
"header": "{\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36\"\n}",
"lastUpdateTime": 0,
"ruleBookInfo": {},
"ruleContent": {
"content": "$.chapter.body"
},
"ruleExplore": {},
"ruleSearch": {
"author": "$.author",
"bookList": "$..books[*]",
"bookUrl": "/Book/getChapterListByBookId?bookId={$._id}",
"coverUrl": "$.cover",
"intro": "$.shortIntro",
"kind": "$.minorCate",
"lastChapter": "$.lastChapter",
"name": "$.title"
},
"ruleToc": {
"chapterList": "$.chapterInfo.chapters.[*]",
"chapterName": "$.title",
"chapterUrl": "$.link"
},
"searchUrl": "/Book/search?query={{key}}&start={{(page-1)*20}}&limit=40&device_type=android&app_version=165",
"weight": 0
}