request+cheerio+iconv-lite+phantomJs制作简单漫画网站爬虫NodeJs项目

简述

我是个喜欢看漫画的人,但是又很贫穷,大部分漫画APP看着看着就要收费了,然后就只能打开浏览器去百度搜来看,比如我常看的‘古风漫画网’;虽然有些时候更新的稍微慢一些,但至少有的看,还是免费。可是又有一些问题。

  1. 广告特别烦,很多时候点击屏幕跳转下一页就会跳到广告,超级烦啊!!!
  2. 然后就是一个页面只能看一张图,这就更烦了,要是和app一样一页到底多好。

正好知道了有 uni-app 这个东西。简单来说,这个uni-app可用vue写页面,然后能打包生成APP(DCloud的团队也太棒了把?)。不过这里主要不是说这个,我要说的是我的服务器项目。

工具

  1. request发起请求,获取页面数据;
  2. cheerio将获取的页面数据(String)转换为可像jQuery一样操作;
  3. iconv-lite处理一些返回的页面数据乱码;
  4. 最最最关键的 phantom 爬取漫画图片链接数据;

PhantomJS是一个无头Web浏览器,可以用JavaScript编写脚本。

我简单的理解是:一个没有可视化界面的浏览器,他和普通浏览器一样能打开一个链接加载页面,只是页面你看不到,但是可以用js来操作。

爬取思路

观察了几个我自己常看几个漫画网站;

漫画数据不是通过接口返回的;
漫画数据也不是一开始就跟着页面数据返回的;
他自己有js函数能获取该章节所有的图片数据;

将某一话的漫画链接在phantomJs中打开,用evaluate执行该漫画网站能获取到剩余图片数据的函数,然后将数据存到数据库中;

梳理流程

漫画网站信息(古风漫画网为例)

  • 需要添加为爬取对象的漫画网站的信息
  • 网址 pathhttps://www.gufengmh8.com
  • 是否支持搜索 searchable(支持)
  • 章节排序方式 listSort(升序)
  • 编码 encoding(UTF-8)
  • 搜索地址 searchPath(/search/)
  • 搜索关键字 keywords(keywords)
  • 搜索结果执行函数 resultCodeJs(作为string类型存到数据库,用eval()执行)
//resultData固定存放数据
/*
	将搜索结果中所有漫画数据存起来
	name 漫画名称
	link 漫画详情链接
	img 漫画封面图
*/
$('#contList li').each(function(){
	const data = {
		name: $(this).find('.cover').attr('title'),
		link: $(this).find('.cover').attr('href'),
		img: $(this).find('img').attr('src')
	};
	resultData.list.push(data);
})
  • 章节结果执行函数 listCodeJs
/*
	获取漫画详情中所有漫画章节
	title 章节名称
	link 章节详情链接
*/
$('#chapter-list-1 li').each(function(){
	const data={
		title: $(this).text().trim(),
		link: $(this).find('a').attr('href')
	};
	resultData.push(data);
})
  • 图片数据执行函数 getImgInfo(用phantomJs打开后执行)
var resultData = {
	pages: SinMH.getChapterImageCount(),
	list: []
};
for(var i=1;i<=resultData.pages;i++){
	resultData.list.push(SinMH.getChapterImage(i));
}

搜索漫画(百炼成神为例)

/*
	web就是事先存储的漫画网站信息JSON数据
	keywords: 前台传的搜索关键字
	将完整搜索地址拼接起来,大概是这样(https://www.gufengmh8.com/search/?keywords=百炼成神)
	用request请求该地址,返回整个搜索结果页面数据(可自行按 F12 看)
	然后用cheerio来转换成类似jQuery的操作,eval()函数执行搜索结果执行函数
*/
let resultData = {
    list: []
};
let rq = new Promise((resolve, reject) => {
	const url = encodeURI(web.path + web.searchPath + '?' + web.keywords + '=' + keywords);
    request.get(url, (err, response, body) => {
        if (!err) {
            let $ = cheerio.load(body);
            eval(web.resultCodeJs);
            resolve(resultData);
        } else {
            reject(err);
        }
    });
});

获取漫画所有章节

/*
	encoding: null body则返回为Buffer,用iconv转码
*/
request.get({url: 漫画详情的地址, encoding: null}, (err, response, body) => {
    if (!err) {
        const content = iconv.decode(body, web.encoding).toString();
        let $ = cheerio.load(content);
        let resultData = [];
        eval(web.listCodeJs);
        ......
    }
});

phantomJs获取漫画图片数据

const phantom = require('phantom');

let sitepage = null; //创建网页对象实例
let phInstance = null; //创建phantomJs实例对象

phantom.create()
	.then(instance => {
		phInstance = instance;
	    return instance.createPage();
	})
    .then(page => {
        sitepage = page;
        return page.open(漫画章节链接地址);
    })
	.then(status => {
		if (status === 'success') {
			const jsCode = 'sitepage.evaluate(function(){'+web.getImgInfo+'return resultData;})';
			const resultData = eval(jsCode);
			return Promise.resolve(resultData);
		}
		return Promise.reject('Phantom打开url失败');
	})

展示

页面确实丑,毕竟没有设计师的能力(┬_┬),但是功能是OK的;
request+cheerio+iconv-lite+phantomJs制作简单漫画网站爬虫NodeJs项目_第1张图片

你可能感兴趣的:(NodeJs,phantomJs)