-
Notifications
You must be signed in to change notification settings - Fork 236
Home
一个站点规则是由三部分组成的:Site, Rule, Selector ,先不说站点规则具体应该怎么写,先来了解这些结构都包含哪些数据,有什么作用
Rule其实就是Selector的集合,其中规定了取不同的数据要使用哪个Selector
而Site就是由多个Rule构成的,其中包括indexRule(用于获取列表), galleryRule(用于获取画册目录)等
public class Site{
int sid;
String title;
String indexUrl, galleryUrl, searchUrl, loginUrl;
Rule indexRule, galleryRule, searchRule, extraRule;
List<Category> categories;
String flag;
}
public class Rule{
public Selector item, idCode, title, uploader, cover, category, datetime, rating, tags, description;
public PictureRule pictureRule;
public VideoRule videoRule;
public TagRule tagRule;
public CommentRule commentRule;
}
public class PictureRule {
public Selector item, id, thumbnail, url, highRes;
}
public class VideoRule {
public Selector id, item, thumbnail, content;
}
public class CommentRule {
public Selector item, avatar, author, datetime, content;
}
public class TagRule {
public Selector item, title, url;
}
public class Selector {
public String selector, fun, param, regex, replacement;
}
先详细介绍最基本的数据类型:
Selector包含5个属性:
jQuery选择器,支持任何jQuery支持的选择器语法
不过为了兼容可能以后会有的iOS和UWP版,建议使用css3标准的伪类
另外特殊情况有一种:this 意味着选中当前元素
(如果不知道什么是jQuery选择器或者css选择器的,你大概不适合继续往下看,如果仍然很有兴趣想学,可以百度jquery选择器,进入w3cschool的页面学习)
对选中的元素使用的方法,目前只支持4种情况:
1.html
效果等同$.html(),即得到元素的内部所有html字符串
2.text
效果等同$.text(),即得到元素的内部字符串去除html标签
3.attr
效果等同$.attr(param),即得到元素的对应属性值
4.null(即不在json中包含这个属性)
效果等于得到包含元素自身的html字符串
正则表达式,应用于使用上述选择器最终得到的字符串上,至少包含一个Group,即使用()包含起来的部分,最终取()中匹配到的值作为最后结果
可为null,即不使用正则表达式
与regex成对使用,单独无效
将经过regex取到的数值,填到replacement里对应的地方,使用 $1 $2 等代表regex里取到的不同组,如:
"rating": {
"selector": "td.itd div div.it4 div",
"fun": "attr",
"param": "style",
"regex": "background-position:-(\\d+)px -(\\d+)px",
"replacement": "5-$1/16-($2-1)/40"
}
<div class="manga_items">
<div class="manga_item">
<img src="http://xxx.com/1.jpg" />
</div>
</div>
我们想要取得img标签的src中的图片地址,那么selector应该怎么写呢?
{
"selector": "div.manga_item > img"
"fun": "attr",
"param": "src"
}
但是假设,我们需要获取缩略图,但是缩略图网址在html中没有
而你知道这个网站的缩略图格式应该是这样: http://xxx.com/thumbnail/1.jpg
那么怎么办呢?就要使用到正则表达式和替换式了
{
"selector": "div.manga_item > img"
"fun": "attr",
"param": "src",
"regex": "(http://xxx.com)/(\\d+\\.jpg)",
"replacement": "$1/thumbnail/$2"
}
Rule是Selector的集合,其中规定了取不同的数据要使用哪个Selector
<div class="manga_items">
<div class="manga_item">
<a class="title" href="http://xxx.com/gallery/10000-1">标题1</a>
</div>
<div class="manga_item">
<a class="title" href="http://xxx.com/gallery/10000-2">标题2</a>
</div>
</div>
Rule实例包含以下 Selector
在indexRule中应该选中每一个独立的画册item,选出的应该是元素集合
在galleryRule中不需要包含此项
下面的每一个Selector都应用在选出的集合中的单例上
且galleryRule获取到的内容会覆盖indexRule获取的部分,例如,indexRule和galleryRule各有一个title的Selector,比如g.e-hentai的列表中标题是英文的,而点进去的详情页获取的是日文标题,则点开后获取到的日文标题会覆盖原标题
比如,按照上面的例子,应该写出的Selector应该是
"item": {
"selector": "div.manga_items>div.manga_item"
}
此处规定了父元素必须是div.manga_items,只是为了确保不会选中多余的元素
能标识出这个item的唯一标识,将会填在Site.galleryUrl的{idCode:}处
例如,如果Site.galleryUrl是 http://xxx.com/gallery/{idCode:}/page/{page:1}
那么这里要获取到的就是 http://xxx.com/gallery/10000-1 中的 10000-1
则要写出的Selector应该为:
"idCode": {
"selector": "a",
"fun": "attr",
"param": "href",
"regex": "gallery/(.*)"
}
注2:正则表达式取出来的只有一个Group时,不需要填写替换式为 "$1" ,会自动取用这个Group
item的评分,会显示在首页的列表中,可选
数值从0到5
注:经过处理最终得到的字符串如果是数字,会转成float,如果得到的是一个数学表达式,则会采用表达式计算结果,其他情况则使用字符串长度作为分数
item的标签,获取到的应该是元素集合,以期能得到复数个tag,如只能获取到一个元素,并最终得到一个包含了复数个tag,并以一定规则分隔的字符串,则使用正则表达式进行获取,所有符合regex的匹配都将加入tags列表,例如:
"tags": {
"fun": "html",
"regex": "([a-zA-Z0-9 -]+)",
"selector": "table.it tr:eq(3) td:eq(1)"
}
bunny girl, fox boy, full color, furry, furry, judy hopps, nick wilde, zootopia, non-h, finnick
新的获取Tag的方法,如果指定了tagRule则tags会被忽略 包含item、title、url三个Selector 例:
"tagRule": {
"item": {
"selector": "div.info > p > span.genre"
},
"title": {
"fun": "html",
"selector": "a"
},
"url": {
"fun": "attr",
"param": "href",
"regex": "(.*)",
"replacement": "$1/page/{page:1}",
"selector": "a"
}
}
一般只在galleryRule中包含
包含item、id、thumbnail、url、highRes五个Selector
例:
"pictureRule": {
"item": {
"regex": "\"http[^\"]*?_\\d{3,4}\\.(?:jpg|jpeg|png|gif|bmp)\"",
"selector": ".photo > a > img"
},
"thumbnail": {
"fun": "attr",
"param": "src",
"regex": "(http[^\"]*?)_\\d{3,4}(\\.(?:jpg|jpeg|png|gif|bmp))",
"replacement": "$1_400$2",
"selector": "this"
},
"url": {
"fun": "attr",
"param": "src",
"regex": "(http[^\"]*?)_\\d{3,4}(\\.(?:jpg|jpeg|png|gif|bmp))",
"replacement": "$1_1280$2",
"selector": "this"
}
}
一般只在galleryRule中包含
包含item、thumbnail、content三个Selector
例:
"videoRule": {
"content": {
"fun": "attr",
"param": "src",
"regex": "(.*)",
"replacement": "https://hanime.tv$1",
"selector": "#video_element"
},
"item": {
"selector": "#video_container"
}
}
选中每一个独立的评论item,选出的应该是元素集合,可选
如果有评论的话可以通过这个Selector获取,没有也不影响,下面所有comment的Selector都是基于这个所选出的item
"indexUrl": "http://g.e-hentai.org/?page={page:0}",
"galleryUrl": "http://g.e-hentai.org/g/{idCode:}/?p={page:0}",
"searchUrl": "http://g.e-hentai.org/?f_search={keyword:}&page={page:0}",
"loginUrl": "https://forums.e-hentai.org/index.php?act=Login"
分别是首页地址、画册目录地址、搜索地址和登录地址,其中登录地址将会在WebView中载入
searchUrl和loginUrl都是可选
其中{page:0}代表填入页数参数的地方,0代表起始数值,有些网站从0开始,有些从1开始
注1:如果有一些网站每次翻页页数增加数值不为1,则参数为{page:起始数字:每次增加}
例如xbooru的URL:http://xbooru.com/index.php?page=post&s=list&pid={page:0:42}
注2:如果想在第一页时不填入page参数,例如绝对领域:
第一页必须是
则Url应该为
其中pageStr标明了page相关的字符串,有pageStr这个参数的url,在page等于起始页时会不填入pageStr参数
即,在page为1时,绝对领域得到的url是 http://www.jdlingyu.moe/cosplay/
{idCode:}就代表能唯一标识一个item的部分
{keyword:}搜索时填入关键词的地方,后面只加冒号因为不需要默认值
另外还有两个可在url中使用的参数:
{date:yyyy-MM-dd:-2} 基准为当前系统时间,yyyy-MM-dd为日期格式,-2为偏移量,单位为天,比如-2就是前天,其中最后一个参数可省略
{time:HH:mm:ss:-300} 基准为当前系统时间,HH:mm:ss为时间格式(不用担心使用了:),-300为偏移量,单位为秒,比如-300是5分钟前,其中最后一个参数可省略
indexRule是首页(和分类)使用的规则
galleryRule是图册目录页使用的规则
searchRule是搜索页使用的规则,此项为可选,如不填则搜索时采用indexRule
extraRule是配合flag使用的Rule
对该站点的item的显示做一些自定义,多个flag用|分隔
目前支持的flag有
标记网站的大图是单页浏览的,图册目录获取到的pictureUrl只是大图浏览页的地址
那么获取大图浏览单页的图片地址的选择器应填入 extraRule→pictureRule→url
预加载图册详情页,使用该flag会在列表中时就预先加载每个item的详情页,并把获取到的数据填入,刷新列表中item的显示
比如pixiv在列表中获取不到tag,tags的Selector是在galleryRule中的,则使用该flag后会预先加载详情页,获取到tag并刷新显示在列表中
标记网站的点开每个item后,还可能要再进行一层跳转才能进入多图的页面,使用该flag后,galleryRule取到的picture的url应为跳转地址而不是图片地址,如果是图片地址则当成正常图片展示,对于跳转的页面的获取规则填入extraRule
前三个分别为标记每个阶段是否需要采用模拟浏览器的方式加载网页,即可以执行初始化js以生成页面,jsNeededAll则是包含前三项
注:使用模拟浏览器方式加载会导致读取速度变慢、并会占用更多资源,除非确定必须执行js才能生成页面,否则不要加这几个flag
下面是一个站点规则的具体JSON:
拿g.e-hentai作为示例,先看JSON,我相信任何一个程序员只需要看一下json就能大致了解每个元素的具体含义,如果有不明白的地方可以再详细看上面的解释:
{
"categories": [
{
"cid": 1,
"title": "首页",
"url": "http://g.e-hentai.org/?page={page:0}"
},
{
"cid": 2,
"title": "同人志",
"url": "http://g.e-hentai.org/doujinshi/{page:0}"
},
{
"cid": 3,
"title": "漫画",
"url": "http://g.e-hentai.org/manga/{page:0}"
}
],
"title": "G.E-hentai",
"indexUrl": "http://g.e-hentai.org/?page={page:0}",
"galleryUrl": "http://g.e-hentai.org/g/{idCode:}/?p={page:0}&hc=1",
"searchUrl": "http://g.e-hentai.org/?f_search={keyword:}&page={page:0}",
"loginUrl": "https://forums.e-hentai.org/index.php?act=Login",
"flag": "singlePageBigPicture|repeatedThumbnail|preloadGallery",
"indexRule": {
"item": {
"selector": "table.itg tr.gtr0,tr.gtr1"
},
"idCode": {
"fun": "attr",
"param": "href",
"regex": "/g/(.*)",
"selector": "td.itd div div.it5 a"
},
"title": {
"fun": "html",
"selector": "td.itd div div.it5 a"
},
"cover": {
"fun": "html",
"regex": "(//|inits?~)(.*?org)[~/]([^~]*\\.jpg)[~\"]",
"replacement": "http://$2/$3",
"selector": "td.itd div div.it2"
},
"uploader": {
"fun": "html",
"selector": "td.itu div a"
},
"category": {
"fun": "attr",
"param": "alt",
"selector": "td.itdc a img"
},
"datetime": {
"fun": "html",
"selector": "td.itd[style]"
},
"rating": {
"fun": "attr",
"param": "style",
"regex": "background-position:-?(\\d+)px -?(\\d+)px",
"replacement": "5-$1/16-($2-1)/40",
"selector": "td.itd div div.it4 div"
}
},
"galleryRule": {
"commentRule": {
"author": {
"fun": "html",
"selector": "div.c3 > a:first-child"
},
"content": {
"fun": "html",
"selector": "div.c6"
},
"datetime": {
"fun": "html",
"regex": "Posted on (.*?) UTC by",
"selector": "div.c3"
},
"item": {
"selector": "div#cdiv > div.c1"
}
},
"pictureRule": {
"item": {
"selector": "div.gdtl,div.gdtm"
},
"thumbnail": {
"regex": "(http://[^\"]*?\\.jpg)",
"selector": "this"
},
"url": {
"fun": "attr",
"param": "href",
"selector": "a"
}
},
"tags": {
"fun": "html",
"selector": "div#taglist table tr td:eq(1) div a"
},
"title": {
"fun": "html",
"selector": "h1#gj"
}
},
"extraRule": {
"pictureRule": {
"url": {
"fun": "attr",
"param": "src",
"selector": "div.sni a img[style]"
}
}
}
}
最后提供一个网页版测试工具:
第一个是测试获取列表的,第二个是测试点开后获取详情的
第一个粘贴站点规则后只需要填入这个规则解析的页面URL,可以用不同地址来测试首页和各个分类、搜索页是否都能成功获取,,只会获取第一页作为测试
第二个是粘贴站点规则后,把第一个站点测试获取到的随便哪个item粘贴进去,就能测试获取这个item的详情,同样只会获取第一页
为了最快掌握用法可以直接把我写好的一个站点的规则粘贴进去,然后粘贴首页地址(记得把page参数的位置改成数字),然后看看结果