.mulu_list li
选择器下面就是我们想要的内容,比较简单,herf
是链接,text
是标题。
首先预想一下,需要一个什么样的文件,提供什么样的功能?于是期望输入一个小说的网址,根据内置的爬取规则获取章节信息,首先保存章节信息到文件里面,然后继续爬取章节里面的内容,存储的地址同样是一个函数输入,并且我们希望控制一下并发量。
首先把它做成命令行的版本,便于直接测试,然后在后续再进行改写。
phin
是一个 node 下,基于net
封装的一个请求模块,非常的小。cherrio
则是类似于jquery
的dom
选取器。iconv-lite
是纯javascript
实现的一个字符编码解码器,主要用于解码 gbk,因为比较老的网站都是 gbk 编码的。jsonfile
可以方便的读取json
文件,保存数据的时候会用到它。url-join
是拼接url
的工具,有考虑到一些有query
的情况,所以使用库拼接,而不是直接字符串拼接。make-dir
用来确保文件地址存在和创建文件。ora
则用于下载进度的显示
pipeP
,第一个参数是 Promise
,之后的参数都是 then
里面的回调,这样就再也不用看见 链了,然后将每一个环节进行分割,具体入下。
// 拉取数据并且转码
const getHTML = (url, charset) => {
return p(url).then(res => decode(res.body, charset))
}
// 装载内容,获取 $ 函数
const loadContent = source => {
const $ = cheerio.load(source)
return selector => {
return $(selector)
}
}
// 去掉 then 链接
const pipeP = (...args) => {
return args.reduce((acc, prev) => acc.then(prev))
}
const buildSelector = (url, charset) =>
pipeP(
getHTML(url, charset),
loadContent
const loadContent = cheerio.load
而对于 getHTML
也可以稍微优化一小下,到这个层次,我觉得就差不多了。
那么还有没有继续优化的空间了呢,是有的。
const decodeHTML = charset => body => decode(body, charset)
const getBody = ({ body }) => body
// 拉取数据并且转码
const getHTML = (url, charset) =>
pipeP(
p(url),
getBody,
)
更多函数式知识请