时间: 2020-09-03 00:08:26 人气: 2277 评论: 0
相信作为一个移动端的老狗,当你遇到一个有内涵的网站的时候,而且当你发现里面有太多的噪音尤其是铺天盖地的 广告 的时候,你是不是有种想把它净化一下的感觉呢?比如来一个纯净版本的。
没错,我最近就在折腾这个,如何把自己欣赏的网站 html 转变为 json,嗯,然后使用flutter啊,小程序啊稍微包装一下,就是自己的小应用,自己自嗨那是多么怡然自得啊!
好,废话多说干嘛,说干就干咯。
那么,server怎么选择呢,我现在玩node,那自然是选择的express了,如果你在玩python,你选择flask也没任何问题,思路嘛,全部都是相通的,人生码路没有绕不过去的坎。自如如何在你自己的小服务器上部署额外的一个express服务,相信读过我之前的文章《服务器上起两个服务,nginx如何转发》和《自己搭建一个server并用nginx反向代理》的化,你很容易起一个express了。当然,如果你只是在本地做做研究,并没打算部署到服务器上,造化千千万万的洁癖狗们,那就免了。
这个完全不用多说什么,直接按照https://expressjs.com/zh-cn/starter/installing.html一通操作就好了。
然后,我想强调的是,express如何做到后台启动,请了解一下pm2最近在用这个,简直爽的不要不要的。
如图所示,查看由pm2管理的node 服务的各种参数,不要太清晰,服务配置有改动,代码有改动直接 pm2 restart 1[id]即可,id上面都有的,一清二楚。听到某个服务,只需要pm2 stop 1。
然后,日志相关的全部放在.pm2的文件夹下,如下图所示
const express = require('express') const cheerio = require('cheerio') const app = express() const request = require('request') var rp = require('request-promise'); const Iconv = require('iconv-lite') const pc = require('phantomjs-cheerio') var Rx = require('rxjs') async function getImages(val) { return await pc.request({url: val.link}).then(($) => { let images = [] $('.view-box .view-main p').each(function () { let image = 'http://www.xiaoliaoba.cn'.concat($(this).find('img').attr('data-src')) images.push(image) }) val.images = images return val }).catch(function (err) { return val }) } async function list(req, res) { let page = parseInt(req.params.page) let url = `http://www.xiaoliaoba.cn/tags/%E5%8A%A8%E6%80%81%E5%9B%BE?page=${page}` let option = { url: url, encoding: null, transform: function (body) { body = Iconv.decode(body, 'utf-8') return cheerio.load(body); } } let results = await rp(option).then(function ($) { links = [] $('.cont-item').each(function () { let header = $(this).find('.cont-editor-head a img').attr('src') let name = $(this).find('.view-editor-name a').text() let time = $(this).find('.view-editor-name span').text() let id = $(this).children().find('.cont-list-in a').attr('href').match(/\d+/)[0] let cover = $(this) .children('.cont-list-main') .find('img') .attr('data-src') let count = $(this) .children('.cont-list-main') .find('span') .text() if (cover != undefined) { let tmp = { name: name, header: header, time: time, title: $(this) .children('.cont-list-title') .text(), cover: 'http://www.xiaoliaoba.cn'.concat(cover), count:count, id: id } links.push(tmp) } }) return links }).catch(function (err) { console.log(err) return [] }) res.send({ code: 200, data: results, msg: '' }) //使用套一个异步 // for (result of results) { // console.log(result) // result.images = await getImages(result.link) // } //使用rxjs的concatmap来做,一样的,你大爷,二次异步请求,网页加载,太耗时!!! // const source = Rx.Observable.of(results) // const example = source.pipe(Rx.Operator.concatMap(val=>getImages(val)),Rx.Operator.toArray()) // const subscribe = example.subscribe(val => // res.send({ // code: 200, // data: val, // msg: '' // }) // ); } app.get('/:page', function (req, res) { if (isNaN(req.params.page)) { res.send({ msg: '请正确填写page参数 int类型', code: 2 }) return false } list(req, res) }) module.exports = app
其实基本的原理就是使用request把网页请求回来,再用cheerio来解析网页,cheerio和jQuery查找dom的操作很像,个人很喜欢这种风格,当然也有xpath那样的库,想用也并不是没有,xpath有一个好处,就是Chrome浏览器中可以直接查看你想要的元素的xpath,可以少手写的点吗,免去耗费脑细胞。
嗯,总结:
一般来说,我们需要使用路由把这个微服务挂钩到express下面
类似于这样app.use('/xx', require('./routes/xx'))
有,当然有,而且我踩了三个
这里你该去了解一下phantomjs,简单的说,他就像是一个浏览器,不过没有界面而已,因此,异步加载的内容这个坑就可以交给他,只不过,这个库巨慢无比,感觉投入使用不大靠谱,但总是可以搞定异步加载的内容。
这时候,就要升级你的node了
我记得貌似我之前是6.x版本,使用async/await操作是报错了的。
这种你应该从代码中可以看到我已经爬了这个坑,那就是对列表中每一项在发起一个异步请求。
我这里尝试过直接for,也用过rx,都是ok的,个人感觉rx的concatMap操作更好,因为他帮你做了并发,你用for await,本质上是一个个在做。