Step 1: 万年不变的初始化项目,安装依赖
cnpm i express cheerio superagent superagent-charset async -S
express 就不用多说了,比较流行的node框架
cheerio 页面数据解析模块。一般都习惯称它node版的jquery,专门用来操作网页dom元素,使用方式和jquery基本相同。
superagent superagent是nodejs里一个非常方便的客户端请求代码模块,superagent是一个轻量级的,渐进式的ajax API,可读性好,学习曲线低,内部依赖nodejs原生的请求API,适用于nodejs环境下。
superagent-charset 很明显,处理编码的。
async 见名知意,node的异步模块。
Step 2: 编写node程序
/* 以爬取起点小说某文为例 */ // 1. 首先引入模块 const cheerio = require('cheerio') const express = require('express') const app = express() const superagent = require('superagent') require('superagent-charset')(superagent) const async = require('async'); let total = 0 // 总章节数 let id = 0 // 计数器 const chapter = 10 // 爬取多少章 const url = 'https://book.qidian.com/info/1011146676#Catalog' // 章节列表页面
// 处理请求 app.get('/',(req,response,next)=>{ superagent.get(url).charset('UTF-8').end((err,res)=>{ var $ = cheerio.load(res.text); // 读取章节列表页面 let urls = [] total = $(".volume-wrap li").length // 获取所以章节元素拿到总章节数
// 循环获取每个章节的页面url并push进urls $('.volume-wrap li').each(function(i,v){ if(i < chapter){ urls.push('http:' + $(v).find("a").attr('href')) } }) // 通过async去请求urls里的地址,并通过fetchUrl方法拆分数据。这里的async.mapLimit方法有点类似es6里的promise.all async.mapLimit(urls,chapter,(url,callback)=>{ id++ fetchUrl(url,callback,id); },(err,results)=>{ response.send(results); }) }) }) // 去空格和空格转义字符 function trim(str){ return str.replace(/(^s*)|(s*$)/g, '').replace(/ /g, '') } // 将Unicode转汉字 function reconvert(str) { str = str.replace(/(&#x)(w{1,4});/gi, function ($0) { return String.fromCharCode(parseInt(escape($0).replace(/(%26%23x)(w{1,4})(%3B)/g, "$2"), 16)); }); return str } // 加载每个章节并拆分数据返回 function fetchUrl(url,callback,id){ superagent.get(url) .charset('UTF-8') .end(function(err,res){ let $ = cheerio.load(res.text); let arr = [] let content = reconvert($(".read-content").html()) const obj = { id: id, err: 0, bookName: $('.text-info a').eq(0).text().substring(1), title: $('.j_chapterName').text(), content: content.toString() } callback(null,obj) }) } // 监听窗口 const PORT = 8080 app.listen(PORT,function(){ console.log("server listening on " + PORT) })
最后,运行node程序,本地打开localhost:8080 就可以看到数据了