示例规则可以参考:示例规则
取值规则
规则格式
所有的规则都遵守:选择器@选择器@选择器@属性[|拼接字符][##要替换的文本[##替换成的文本]][@js: js代码]
其中[]内为可选
选择器格式
css选选择器。例如:.class、#id、div
标签选择器,格式为tag.标签。例如:tag.div、tag.img
类选择器,格式为class.类。例如:class.content、class.items
自身选择器,特定值【self】。1.1.1版本新增
属性可选值
text:获取元素的文本内容
textNodes:遍历所有的子节点的文本内容,之后拼接在一起
html:获取元素的html代码,包含自身标签
innerHTML:获取元素内的html代码,不包含自己
all:同html
其他:比如src、href...,如果不是上述的5个,则会获取元素的属性
拼接字符
不常用,有时,我们可能获取到多个内容,比如标签,此时就可以加个拼接字符,比如:
.content@.item@text|、
此处的意思是,获取【.content】中所有的【.item】元素,之后获取【文本】内容,使用【、】进行拼接
替换规则
有时,我们获取的内容中可能存在一些广告,一些链接,我们希望替换掉,就可以使用替换规则,替换成的文本可以不输入,默认为空字符串
.content@text##你好##hello
.content@text##wwww.aaa.com
第一行是指将获取的文本中【你好】替换成【hello】
第二行是指将获取的文本中【www.aaa.com】替换成【】空字符串
链接字符
上面说的都是单一取值,但是有的时候,我们也需要通过多个不同的选择器进行取值,此时就可以使用链接字符,链接字符的左右都必须是完整的选择器,例如:
.content@.item@text||.summary@text
上面的选择器就表示,取第一个有值的,如果【.content@.item@text】获取到了值就不处理后面的选择器了。
替换字符一共有三种
||:取第一个有值的
&&:获取全的的值,英文逗号拼接
%%:依次获取所有的值,大部分情况下与&&得到的结果一致,只有在列表规则是有区别,主要是列表的顺序有区别
js代码
一个完整的规则只能有一个js代码,可以拼接在最后,使用@js:开头,例如,我们在解析1链接时,链接很有可能没有包含域名。就可以使用js代码,如下:
tag.a@href@js: `https://example.com/${result}`
其中,result
为前面获取到的内容,上面的规则,比如tag.a@href
解析到的是item/1.html
,则最后的结果为:https://example.com/item/1.html
示例
比如掘金的列表规则
最终显示的效果
内容规则
单独把内容规则提取出来,是因为内容规则可以不仅仅使用上面的取值规则,还可以通过模板的方式对内容进行重新排版
选项
自定义渲染:如果关闭,则内容就是上面的取值规则,如果开启,则根据渲染方式进行渲染
渲染方式:模板是插值,js函数式返回html字符串,下面会详细介绍
内容:根据上面两个选项,此处填写的内容也会不一样,下面会详细介绍
普通渲染
此时自定义内容渲染关闭,内容则填写取值规则,比如说我的博客,由于内容比较规范,所以就进行普通渲染
类型定义
在看模板渲染、js函数渲染前,首先需要了解函数定义,知道可以使用那些方法获取内容
export interface ParserEngine {
/**
* 根据规则解析为字符串
* @param select 规则
*/
parseToString(select: string): string;
/**
* 根据规则解析为引擎数组,每个元素为一个引擎实例
* @param select 规则
*/
parseToEngines(select: string): Array<ParserEngine>;
/**
* 解析正则列表
* @param regex 正则表达式
* @param selects 选择器列表
* @deprecated 请使用 parseToString
*/
parseRegexToStrings(regex: string, selects: Array<string | undefined>): Array<Array<string>>;
/**
* 将当前内容转为字符串
*/
toString(): string;
/**
* 将当前内容转为 HTML 字符串,包含元素本身
*/
toHTML(): string;
/**
* 将当前内容转为 HTML 字符串,不包含元素本身
*/
toInnerHTML(): string;
}
在下面两种渲染模式中,可以获取一个root对象,该对象为初始html解析后获取到的对象,所有的操作都基于此
模板渲染
此时,自定义内容渲染打开,渲染方式选择模板
此种方式适合取值比较简单,但是样式需要自定义的情况。例如博客平台,各种文章、内容平台
比如说v2ex,具体语法为:
<div>{{root.parseToString('.topic_content@html') }} </div>
<style>
.fr {
float: right;
text-align: right;
}
.sep3 {
height: 3px;
}
.badges {
display: inline-flex;
cursor: default;
}
.sep5 {
height: 5px;
}
.reply_content {
font-size: 14px;
line-height: 1.6;
word-break: break-word;
}
.cell {
border-bottom: 1px solid #4b5052;
padding: 10px;
}
.small.fade {
display: inline-flex;
line-height: 16px;
height: 16px;
overflow-y: hidden;
}
</style>
<div style="margin-top: 16px">{{root.parseToString('.box[4]@html') }} </div>
其中,内容为一段html代码,其中,可以使用{{ }},在中间可以编写js代码,注意,此处不可换行
比如说v2ex,内容上比较简单,
js渲染
此时,自定义内容渲染打开,渲染方式选择js函数
顾名思义,此处的内容就不是上面模板渲染那样是一个html代码了,此处是一个js函数,需要返回一个html,可以使用
比如说猿聊,具体语法示例:
const engines = root.parseToEngines('.CommentPost.Post')
const list = [];
for (let engine of engines) {
const username = engine.parseToString('.item-user@text');
const body = engine.parseToString('.Post-body@html');
const avatar = engine.parseToString('.Avatar@src');
const time = engine.parseToString('.item-meta@.Dropdown-toggle@text');
list.push(`<div role="listitem" class="arco-list-item no-padding">
<div class="arco-list-item-main">
<div class="arco-list-item-content">
<div class="arco-list-item-meta">
<div class="arco-list-item-meta-avatar">
<div class="arco-avatar arco-avatar-square">
<span class="arco-avatar-image">
<img alt="avatar" src="${avatar}">
</span>
</div>
</div>
<div class="arco-list-item-meta-content">
<div class="arco-list-item-meta-title">
<span>${username}</span>
<span class="arco-tag arco-tag-size-medium arco-tag-arcoblue arco-tag-checked ml-8">${time}</span>
</div>
<div class="arco-list-item-meta-description">
</div>
</div>
</div>
<div>${body}</div>
</div>
</div>
</div>`)
}
return `
<div class="arco-list-wrapper">
<div class="arco-spin arco-list-spin">
<div class="arco-scrollbar arco-scrollbar-type-embed">
<div class="arco-scrollbar-container arco-list arco-list-medium arco-list-split">
<div class="arco-list-content-wrapper">
<div role="list" class="arco-list-content">
${list.join('\n')}
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.no-padding{
padding: 0 !important;
}
.ml-8 {
margin-left: 8px;
}
</style>
`
评论区