记一次nodejs 爬虫(利用递归循环nightmare)

Posted juvenilelin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次nodejs 爬虫(利用递归循环nightmare)相关的知识,希望对你有一定的参考价值。

记一次nodejs 爬虫(利用递归循环nightmare)

新手,欢迎交流

目标网站

技术图片

技术图片

这里的网址很有规律,方便我们获取图书列表的url

nightmare几个主要的api 具体参考:http://www.manongjc.com/detail/8-roxmpabfhewimht.html

  • .goto(url,options) url:目标网站 options:伪造头部信息

  • .wait(callback[selector]) 这个方法会重复调用,直到 return true,

    可以传入选择器,如: .wait(‘body‘) 意指等待body加载完成

  • .inject(type, file) 注入本地文件,type: css js

  • .evaluate(callback) 这里的返回值可以在.then方法中接收到

  • .then() 获得处理结果

  • .catch() 抛出错误

  • .end() 关闭浏览器,注意关闭后调用不了goto 方法,如果需要循环请求url,不能调此方法

note: .wait&.evaluate中的代码要做浏览器中运行

爬取书籍列表

var Nightmare = require(‘nightmare‘);       
var nightmare = Nightmare({ show: true });
var fs = require(‘fs‘);
var mysql = require(‘mysql‘);
var async = require(‘async‘);

let options = {
				host:‘localhost‘,
				port:‘3306‘,
				user:‘root‘,
				password:‘root‘,
				database:‘juveniledata‘
}
var connection = mysql.createConnection(options);
connection.connect(function(err){
	if(err){
		console.log(err);
	}else{
		console.log(‘database连接成功‘)
	}
});

 function funcasy(i,connection){
	nightmare
		.goto(`http://item.kongfz.com/Cxiaoshuo/tag_k34k33k30k30k35w${i}/`,{
				‘User-Agent‘: ‘Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (Khtml, like Gecko) Crios/19.0.1084.60 Mobile/9B206 Safari/7534.48.3‘,
				‘Accept‘: ‘text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3‘,
				
				‘Accept-Language‘: ‘zh-CN,zh;q=0.9‘,
				‘Cache-Control‘: ‘no-cache‘
			})
		
		.wait(function(){
			if(document.getElementsByClassName(‘result-list‘)[0]) return true;
		})
		.wait(function(){
			window.lyharr = [];
			return true;
		})
		.wait(function(){
			var gethreflyh = document.querySelectorAll(‘#listBox .item-img a:first-of-type‘);
			for(let j=0;j<gethreflyh.length;j++){
				window.lyharr.push(gethreflyh[j].href);
			}
			return true;
		})
		.evaluate(function(){
			return window.lyharr;
		})
		.then(function(results){
			let values = ‘‘;
        // 向数据库插入多条数据
        // insert into tablename values (),(),()...
			for(let i = 0;i<results.length;i++){
			    values += `(null,"${results[i]}"),`;
				if(i == results.length -1){
					values = values.substring(0,values.length-1);
				}
			}
			let sqlstr = `insert into bookurl2 values` + values;
			connection.query(sqlstr,function(err,results,fields){
				if(err) console.log(err);
				console.log(‘database success‘);
                // 递归
				if(i<100) funcasy(i+1,connection);
			});
			
		})
		.catch(function(err){
			console.log(err);
		})
}
funcasy(1,connection);

运行结果保存在数据库中:

技术图片

note: 原本打算爬取100页的书籍列表,中途出现验证码

根据书籍列表的url,获取具体的书籍信息

技术图片

技术图片

信息比较多,选取我们需要的

好在查看详情已经在服务器渲染好了,不需要我们模拟点击

var Nightmare = require(‘nightmare‘);       
var nightmare = Nightmare({ show: true });
var fs = require(‘fs‘);
var mysql = require(‘mysql‘);
var async = require(‘async‘);

let options = {
				host:‘localhost‘,
				port:‘3306‘,
				user:‘root‘,
				password:‘root‘,
				database:‘juveniledata‘
}
var connection = mysql.createConnection(options);
connection.connect(function(err){
	if(err){
		console.log(err);
	}else{
		console.log(‘database连接成功‘)
	}
});

function getbookinfo(i,connection){
	let sqlstr = `select bookurl2 from bookurl2 where id = "${i}" `;
	connection.query(sqlstr,function(err,results,fields){
		if(err) console.log(err);
		console.log(results[0].bookurl2);
		
		nightmare
				.goto(results[0].bookurl2,{
					"Accept" : "application/jason, text/javascript, */*; q = 0.01",
					    "X-Request-With" : "XMLHttpRequest",
					    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; ...) Gecko/20100101 Firefox/60.0",
					    "Content-Type" : "application/x-www-form-urlencode:chartset=UTF-8"
				})
				.wait(function(){
					
					window.lyharr = [];
					return true;
				})
				.inject(‘js‘, ‘jquery-3.4.1.min.js‘)
				.wait(‘.detail-con .clearfix‘)
				.wait(function(){
					window.lyharr.push($(‘h1[class="detail-title"]‘).text());// 书名
					window.lyharr.push(($(‘span:contains("作者")‘).next()).text().replace(/ +/g,""));  
					window.lyharr.push(($(‘span:contains("出版社")‘).next()).text()); 
					window.lyharr.push(($(‘span:contains("出版时间")‘).next()).text());
					window.lyharr.push(($(‘span:contains("ISBN")‘).next()).text());
					window.lyharr.push(($(‘span:contains("定价")‘).next()).text());
					window.lyharr.push(($(‘span:contains("页数")‘).next()).text());
					window.lyharr.push(($(‘span:contains("分类")‘).next()).text());
					// 内容简介
					window.lyharr.push($(‘li:contains("内容简介")‘).text().replace(/ +/g,""));
					// 作者简介
					window.lyharr.push($(‘li:contains("作者简介")‘).text().replace(/ +/g,""));
					// 图片地址
					window.lyharr.push($(‘div[class="detail-img"] a:first-of-type‘).attr(‘href‘));
					
					return true;
				})
				.evaluate(function(){
					return window.lyharr;
				})
				.then(function(results){
					// console.log(results);
					let sqlsql = `insert into bookinfo2 values(null,"${results[0]}","${results[1]}","${results[2]}","${results[3]}","${results[4]}","${results[5]}","${results[6]}","${results[7]}","${results[8]}","${results[9]}","${results[10]}")`;
					connection.query(sqlsql,function(err,results,fields){
						if(err)console.log(err);
						console.log(‘database sucess‘);
						if(i<=1000) getbookinfo(i+1,connection);
					});
				})
				.catch(function(err){if(err) console.log(err);});
	});
}
getbookinfo(1,connection);

运行数据库结果:

技术图片

切记:循环时,不能调用 .end() 方法

以上是关于记一次nodejs 爬虫(利用递归循环nightmare)的主要内容,如果未能解决你的问题,请参考以下文章

记一次SqlServer骚操作——递归

记一次JVM故障排除

记一次Python爬虫开发经历

记一次企业级爬虫系统升级改造:文本分析与数据建模规则化处理

nodejs爬虫笔记---利用nightmare模拟点击下一页

记一次爬虫框架的开发经历