万智牌已经弃坑了快四年了,现在每次大学聚会的时候大家说打几把牌,而这种频率每年也就一两次,实在是没必要用实体的了。所幸有magiccards.info这个网站,他提供了一个功能,可以生成所选卡图的页面,然后可以直接去外面打印这个页面,打印的效果也非常不错,但根据牌表一张一张去加,实在是有点精污,于是想到可以使用代码来解决一下这个问题。
目前想到的流程是:
- 准备好牌表的文本文件
- 服务器接收一下文件,读取每一行的卡牌名称,然后去magiccards获取这张牌的系列编码和id
- 回传给页面后,由页面来访问magiccards的卡图接口,由页面来做这个事是因为这个应该是记录在cookie里的,不能由服务器访问,不然最后的结果页面看不到
服务端
服务端只需要做一个页面,和一个接口就可以。因为整体使用了co的方式,所以读取文件这里,使用了co-fs
插件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| let input = yield fs.readFile(req.file.path, 'utf8'), cards = [], line = ""; for(let i = 0, len = input.length; i < len; i++){ let tmp = "", chari = input[i]; if(chari == "\n"){ tmp = yield webReader.read(line); cards.push(tmp); (async function(){ await sleep(200); })(); line = ""; }else{ line += chari; } } console.log("all done"); return {error: 0, data: cards}; function sleep(ms){ return new Promise(resolve => setTimeout(resolve, ms)) }
|
其中
webReader
这个对象是自己写的模块,主要完成根据这一行的卡牌名称,抓取网页信息,获得系列编码和id。每次抓取之间加了200ms的间隔。
在webReader
这个模块中,主要使用了cheerio
这个插件,然后还需要转一下编码。
1 2
| let superagent = require("superagent"); require('superagent-charset')(superagent);
|
根据卡牌的名称,去抓取这张卡牌的搜索页面中,对应的卡牌系列编码和id,返回即可。
cheerio
这个插件的使用类似于jquery,通过研究页面的结构,层层递进,直到把需要的数据拿到为止。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| const logger = require("log4js").getLogger("webReader.js"), co = require('co'), $ = require('cheerio'), browserMsg = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36", 'Content-Type': 'application/x-www-form-urlencoded' }, BASE_URL = "https://magiccards.info/"; module.exports.read = function(txt){ return co(function *(){ let cookie = { }, geturl = BASE_URL + "query"; geturl = getAllUrlAddress(geturl, txt); var httpres = yield superagent .get(geturl) .set("Cookie", cookie) .set(browserMsg) .charset("utf-8");
let htmlbody = $.load(httpres.text), tmp = htmlbody("html").find("table").eq(3).find("td").eq(1).find("span").eq(0).find("a").eq(0);
return tmp[0].attribs.href; }).then(function(result){ return result; }).catch(function(error){ logger.error(error); }); }; function getAllUrlAddress(url, str){ url += "?"; str = myTrim(str); let idx = str.indexOf(" "); str = str.substring(idx + 1); str = str.replace(/\s/g, "+"); return url + "q=" + str; }
|
返回到页面后,拿到的是卡牌的数组,依次去访问网站的添加页面即可。