转自知乎@深红
多多猫是一款比较另类的app
只提供插件不提供内容
它以插件形式提供开放平台,只要熟悉HTML,CSS,JavaScript,即可成为插件开发者。
插件有漫画,轻小说,视频,图片,资讯等各种分类,分别提供不同的内容。
如果你没听过这款软件,可以试着用一下(并没有利益相关),这样对于插件的开发和使用,也有个基本概念。
多多猫插件,可以看作是一个爬虫,运行在多多猫这个容器里,数据的解析和渲染由容器支持,而我们只需要编写函数告诉容器,应该怎样获取数据即可。
插件的开发文档可以在官网下载。
下面,我们来开发一个资讯类的插件,功能是:浏览2DFan的游戏列表和排行榜,并且可以点击进入详情页。
准备工作
手机下载多多猫
电脑和手机在同一wifi下(便于在手机上调试插件)
电脑安装一个本地服务器,比如XAMPP(下面的教程,就以XAMPP为例)
测试手机能否访问本地电脑
开启apache服务器,打开终端(win+r,输入cmd),输入ipconfig
找到ip地址,比如上图中,ip地址是192.168.191.3,于是在手机上访问192.168.191.3:8080(注意:端口号不一定是8080,由你本地apache的配置决定),如果出现欢迎界面,说明手机访问本地电脑成功。
编写插件
在xampp安装目录下的htdocs文件夹下新建一个文件,命名2dfan.sited(注意:插件的后缀名均为sited), 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<sited ver="1" debug="1" engine="27" schema="1">
<meta>
<ua></ua>
<title>2DFan</title>
<intro>2DFan(二次元爱好者)是一个专注于提供日本游戏、动漫相关内容的门户站点</intro>
<author>deepred</author>
<url>www.2dfan.com</url>
<expr>\.2dfan\.com</expr>
<encode>utf-8</encode>
</meta>
<main dtype="6" durl="http://www.2dfan.com/subjects">
<home>
<hots cache="1d" title="首页" method="get" parse="hots_parse" url="http://www.2dfan.com/subjects" />
<tags title="标签">
<item title="游戏列表" url="http://www.2dfan.com/subjects/page/@page" />
<item title="排行榜" url="http://www.2dfan.com/subjects/top" />
</tags>
</home>
<tag cache="1d" method="get" parse="tag_parse" />
<book cache="1d" method="get" parse="book_parse" />
</main>
<script>
<require>
<item url="http://sited.noear.org/addin/js/cheerio.js" lib="cheerio" />
</require>
<code>
<![CDATA[
]]>
</code>
</script>
</sited>
手机打开多多猫,在搜索框中输入:192.168.191.3:8080:/2dfan.sited,于是多多猫就安装了我们本地的插件
我们自己编写的函数是写在code标签里的
<code>
<![CDATA[
]]>
</code>
注意这段代码
<hots cache="1d" title="首页" method="get" parse="hots_parse" url="http://www.2dfan.com/subjects" />
它的意思是:打开插件后,默认调用hots_parse函数,该函数要访问http://www.2dfan.com/subjects的资源,于是我们开始写hots_parse函数
插件开发文档要求hots_parse函数返回一个数组,每一项都是个对象,包含name,url,logo三个属性。
我们先来访问http://www.2dfan.com/subjects,发现页面是这样的结构:
页面是由多个li组成,每个li即可解析出一个对象
{
name: "トリノライン",
url: "http://www.2dfan.com/subjects/6997",
logo: "http://img.2dfan.com/uploads/subjects/packages/852f2897cc56d965486f887a6b4b92d8.jpg?imageMogr2/quality/85!/thumbnail/180x240"
}
多多猫插件内置了cheerio库,所以解析dom时可以直接使用jQuery的api
注意:函数最后要返回json字符串
<![CDATA[
function hots_parse(url, html) {
var $ = cheerio.load(html);
var list = [];
var games = $('#subjects li.media');
var host = 'http://www.2dfan.com';
games.each(function() {
var game = $(this);
var name = game.find('h4 a').text();
var url = host + game.find('h4 a').attr('href');
var logo = game.find('img').attr('src');
list.push({
name: name,
url: url,
logo: logo
});
});
return JSON.stringify(list);
}
]]>
重新加载插件,可以发现首页访问成功了
接着看这段代码
<book cache="1d" method="get" parse="book_parse" />
它表示,当我们点击进入详情页时,就调用book_parse函数,要求函数返回如下格式:
我们访问http://www.2dfan.com/subjects/6997
这段简介就是我们想要解析的内容,它由多个p标签组成,每个p即可解析成一个对象
{
d: "妹妹死了",
t: 1
}
function book_parse(url, html) {
var $ = cheerio.load(html);
var list = [];
var logo = $('.media img').attr('src');
list.push({
d: logo,
t: 9
}, {
d: '游戏简介',
t: 1
});
$('blockquote p').each(function() {
list.push({
d: $(this).text().trim(),
t: 1
})
});
return JSON.stringify(list);
}
刷新插件,这次我们可以点击进入详情页了
<tags title="标签">
<item title="游戏列表" url="http://www.2dfan.com/subjects/page/@page" />
</tags>
注意:
http://www.2dfan.com/subjects/page/@page
这样的写法,多多猫容器可以自动实现上拉加载新的一页
<tag cache="1d" method="get" parse="tag_parse" />
这段代码表示,点击标签页时,调用tag_parse函数,该函数要求返回如下格式:
可以发现,基本和hots_parse函数相同,只是多个几个属性
function tag_parse(url, html) {
var $ = cheerio.load(html);
var list = [];
var games = $('#subjects li.media');
var host = 'http://www.2dfan.com';
games.each(function() {
var game = $(this);
var name = game.find('h4 a').text();
var url = host + game.find('h4 a').attr('href');
var logo = game.find('img').attr('src');
var author = game.find('p.control-group span a').text();
var status = game.find('p.control-group .muted').text();
list.push({
name: name,
url: url,
logo: logo,
author: author,
status: status
});
});
return JSON.stringify(list);
}
完整代码
<?xml version="1.0" encoding="utf-8"?>
<sited ver="1" debug="1" engine="27" schema="1">
<meta>
<ua></ua>
<title>2DFan</title>
<intro>2DFan(二次元爱好者)是一个专注于提供日本游戏、动漫相关内容的门户站点</intro>
<author>deepred</author>
<url>www.2dfan.com</url>
<expr>\.2dfan\.com</expr>
<encode>utf-8</encode>
</meta>
<main dtype="6" durl="http://www.2dfan.com/subjects">
<home>
<hots cache="1d" title="首页" method="get" parse="hots_parse" url="http://www.2dfan.com/subjects" />
<tags title="标签">
<item title="游戏列表" url="http://www.2dfan.com/subjects/page/@page" />
<item title="排行榜" url="http://www.2dfan.com/subjects/top" />
</tags>
</home>
<tag cache="1d" method="get" parse="tag_parse" />
<book cache="1d" method="get" parse="book_parse" />
</main>
<script>
<require>
<item url="http://sited.noear.org/addin/js/cheerio.js" lib="cheerio" />
</require>
<code>
<![CDATA[
function hots_parse(url, html) {
var $ = cheerio.load(html);
var list = [];
var games = $('#subjects li.media');
var host = 'http://www.2dfan.com';
games.each(function() {
var game = $(this);
var name = game.find('h4 a').text();
var url = host + game.find('h4 a').attr('href');
var logo = game.find('img').attr('src');
list.push({
name: name,
url: url,
logo: logo
});
});
return JSON.stringify(list);
}
function book_parse(url, html) {
var $ = cheerio.load(html);
var list = [];
var logo = $('.media img').attr('src');
list.push({
d: logo,
t: 9
}, {
d: '游戏简介',
t: 1
});
$('blockquote p').each(function () {
list.push({
d: $(this).text().trim(),
t: 1
})
});
return JSON.stringify(list);
}
function tag_parse(url, html) {
var $ = cheerio.load(html);
var list = [];
var games = $('#subjects li.media');
var host = 'http://www.2dfan.com';
games.each(function() {
var game = $(this);
var name = game.find('h4 a').text();
var url = host + game.find('h4 a').attr('href');
var logo = game.find('img').attr('src');
var author = game.find('p.control-group span a').text();
var status = game.find('p.control-group .muted').text();
list.push({
name: name,
url: url,
logo: logo,
author: author,
status: status
});
});
return JSON.stringify(list);
}
]]>
</code>
</script>
</sited>
这只是一个非常简单的插件教程,更多的功能可以由大家自行开发。