NodeJs|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执行该漫画网站能获取到剩余图片数据的函数,然后将数据存到数据库中;
梳理流程 漫画网站信息(古风漫画网为例)
  • 需要添加为爬取对象的漫画网站的信息
  • 网址 path(https://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 = https://www.it610.com/article/{ 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=https://www.it610.com/article/{ title: $(this).text().trim(), link: $(this).find('a').attr('href') }; resultData.push(data); })

  • 图片数据执行函数 getImgInfo(用phantomJs打开后执行)
var resultData = https://www.it610.com/article/{ 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 = https://www.it610.com/article/{ 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 = https://www.it610.com/article/[]; 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 = https://www.it610.com/article/eval(jsCode); return Promise.resolve(resultData); } return Promise.reject('Phantom打开url失败'); })

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


    推荐阅读