转自@夜明的孤行灯
最近看漫画有点多,因为各种各样的原因各个网站的漫画都不全,好不容易找到一个好用的,估计服务器不在大陆,速度特别慢。但是又只有网页版本,自然没有各种缓存,离线 下载功能了。
本来寻思自己写一个,但是在知乎看到一个推荐多多猫的,就简单尝试了一下,果然不要自己造轮子呀。
多多猫这个app本身是没有任何内容的,它只是一个插件容器,内容来源是需要插件实现的。而插件的标准(?)名为sited,是xml格式,具体代码实现是javascript。简单来说文档是有的,而且只找到了一份官方的,可以看出有些内容并没有及时更新,但是照着做一个还是没有问题的。
简单来说一下这个漫画网站的结构,主页就是一个列表,每个漫画有分页,一页10张图,一般一个漫画200张左右,就是一个没有目录结构的顺序图集。
先来看看插件大体格式
<?xml version="1.0" encoding="utf-8"?>
<sited ver="1" debug="0" engine="32" schema="1">
<meta>
<title>XXX漫画</title>
<encode>utf-8</encode>
<ua>Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87
Safari/537.36
</ua>
</meta>
<main dtype="4" durl="xxx">
<home>
<hots cache="10m" title="首页" method="get" parse="hots_parse" url="xxx" showWeb="0"
showImg="2"/>
</home>
</main>
<script>
<require>
<item url="http://sited.noear.org/addin/js/cheerio.js" lib="cheerio"/>
</require>
<code>
</code>
</script>
</sited>
主要结构是meta,main和script三大块。其中meta主要是插件的一些信息,main定义的逻辑节点,比如主页,tag,详细页面等等,script中是具体的处理逻辑。
每一块的所有属性都在文档中有这里就不细说了。先来看看home块,最关键的是parse属性,这里定义的是处理方法,而根据文档需要返回一个对象,包含了name,logo,url三个属性。
function hots_parse(url, html) {
var $ = cheerio.load(html);
var list = [];
$('.post_box').each(function () {
var slf = $(this);
var bm = {};
bm.name = slf.children("div.c-top").find('a').text();
bm.url = urla(slf.children("div.c-top").find('a').attr('href'));
bm.logo = urla(slf.children("div.c-con").find('img').attr('src'));
list.push(bm);
});
return JSON.stringify(list);
}
这里依赖了cheerio作为网页解析,而返回的是一个json格式的list,当然具体的解析逻辑要根据需求来。
具体的详细页面的解析式定义在book块中,根据文档这里有两个函数,一个是根据网址返回一个图片地址列表,一个是根据网址返回要处理的网址。
根据网站的结构,在列表页获取的只是漫画的前十张图,还需要获取所有的分页地址,然后再处理,所以这里两个函数都需要。
<book cache="1d" method="get" parse="book_parse" parseUrl="book_parse_url" showWeb="0" showImg="2"/
先来看看book_parse_url函数
function book_parse_url(url, html) {
var $ = cheerio.load(html);
var list = [];
var max = $('.single-navi').last().text();
for (var i = 1; i <= max; i++) {
list.push(url + '/' + i);
}
return list.join(';');
}
这里返回的是一个字符串,而具体的处理函数返回的是一个列表
function book_parse(url, html) {
var $ = cheerio.load(html);
var list = [];
$('.entry-content').children("p").each(function () {
var slf = $(this);
list.push(slf.children("img").attr('src'));
});
return JSON.stringify(list)
}
这样就实现了整个插件的核心逻辑,可以自由浏览漫画,同时因为多多猫作为插件容器实现了通用功能,这样也就拥有了历史记录,离线下载,收藏等功能了。
总的来说多多猫和sited插件体系是一个很有意思的东西,对于不同资源的定义和插件标准的设计能否覆盖大部分需求,唯一的问题就是开发时如果有任何问题要么显示插件格式解析失败,要么就是白页面,所以调试基本靠脑补。不过好在代码量不大,出错几率也不是很高。