2021-02-06
阅读:35
首先,确保你已经安装了node,如果没有,可以参考node开发环境搭建
新建一个文件夹,目录名随便起一个,在根目录下执行
//初始化package.json文件
npm init
//引入cheerio模块
npm install cheerio --save
//引入定时任务模块
npm install node-schedule --save
//引入axios
npm install axios --save
cheerio 是一个 jQuery Core 的子集,其实现了 jQuery Core 中浏览器无关的 DOM 操作 API,去掉了jQuery的一些效果类和请求类等等功能后,仅保留核心对dom操作的部分,因此能够对dom进行和jQuery一样方便的操作 具体操作可以查看cheerio中文文档
node-schedule 是一个在node中实现定时任务的模块,使用他可以很方便的实现定时任务,具体使用方法可以参考文档
这里,我们使用axios进行网页内容爬取,先对axios进行封装,可以伪装成浏览器访问、添加cookie等操作,新建api.js文件
const axios = require('axios');
const server = axios.create({
timeout:10000,
headers:{//模拟浏览器访问
'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'
}
});
module.exports = {
get(url){
return server.get(url);
},
post(url,data){
return server.post(url,data);
}
}
原理是,先通过axios==发送get请求,获取到目标网站返回的html代码,再通过==cheerio获取到你想要得到的数据等信息
这里,我们已文章网站为例,爬取文章列表、以及文章内容
先审查元素,查看目标网站上你想要获取内容部分的dom结构、class类名、id等信息
这里我们以文章网站为例
我们需要文章标题、图片列表、文章分类、作者、文章详情跳转链接等信息,通过审查源代码,我们找到文章列表下的dom 找到这些信息对应的class类名、id名称,然后通过cheerio获取出这些信息,组合成你需要的信息 例如
const $http = require('./api.js');
const schedule = require('node-schedule');
const cheerio = require('cheerio');
let list = [];
//这里定义了目标网站的一些文章分类列表的链接
let baseList = [
"https://cpu.baidu.com",
"https://cpu.baidu.com/?chn=1022&from=list",
"https://cpu.baidu.com/?chn=1021&from=list",
"https://cpu.baidu.com/?chn=1001&from=list",
"https://cpu.baidu.com/?chn=1013&from=list",
"https://cpu.baidu.com/?chn=1048&from=list",
"https://cpu.baidu.com/?chn=1006&from=list",
"https://cpu.baidu.com/?chn=1002&from=list",
"https://cpu.baidu.com/?chn=1007&from=list"
];
//随机获取列表
function getList(){
return new Promise((resolve,reject)=>{
let index = Math.floor((Math.random()*baseList.length));
let url = baseList[index];
$http.get(`${url}`).then((res)=>{
if(res.status == 200){
let data = res.data;
let $ = cheerio.load(data);
let ls = [];
$("#main-content .news-list .news-item").each(function(i,e){
let item = {};
item.title = $(e).find(".n-title span").text();
let imglist = [];
$(e).find('.n-img-wrapper .img').each(function(j,v){
let img_item = $(v).find('img').attr('data-src');
if(img_item.indexOf('http') < 0){
img_item = 'https:' + img_item;
}
if(imglist.length < 3){
imglist.push(img_item);
}
});
//判断图片数量
if(imglist.length >=3){
item.extra = imglist;
}
//获取来源
let source_name = $(e).find(".n-desc .info span").eq(1).text();
item.source_name = source_name;
//详情链接
let url = $(e).find('.n-item-link').attr('href');
//判断分类
let cat_info = $(e).find('.n-desc .info .cat-info').text();
item.cat_info = cat_info;
//自定义分类id
if(cat_info == "娱乐"){
item.catid = "20006";
}else if(cat_info == "科技"){
item.catid = "20014";
}else if(cat_info == "财经"){
item.catid = "20013";
}else if(cat_info == "体育"){
item.catid = "20076";
}else if(cat_info == "汽车"){
item.catid = "20016";
}else if(cat_info == "社会"){
item.catid = "1048";
}else if(cat_info == "游戏"){
item.catid = "1040";
}else if(cat_info == "时尚"){
item.catid = "20090";
}else if(cat_info == "三农"){
item.catid = "20091";
}else if(cat_info == "手机"){
item.catid = "20092";
}else if(cat_info == "房产"){
item.catid = "20093";
}else if(cat_info == "鸡汤美文"){
item.catid = "20094";
}else if(cat_info == "相声小品"){
item.catid = "20095";
}else if(cat_info == "美食"){
item.catid = "20096";
}else if(cat_info == "星座"){
item.catid = "20097";
}
item.url = url;
ls.push(item);
})
resolve(ls);
}else{
console.log("请求失败");
reject('222');
}
})
})
}
//获取文章详情
function getContent(url){
return new Promise((resolve,reject)=>{
$http.get(`https://cpu.baidu.com${url}`).then((res)=>{
if(res.status == 200){
resolve(res.data);
}
})
})
}
async function init(){
if(list.length == 0){
list = await getList();
}
let data = list.pop();
if(data.title.length > 40){
console.log('文章标题过长,不采集');
return;
}
if(data.title && data.extra){
let html = await getContent(data.url);
let $ = cheerio.load(html,{decodeEntities:false});
let thumb = data.extra[0] || "";
data.extra = JSON.stringify(data.extra);
$("#main-content .article").find('img').each(function(i,e){
let url = $(this).attr("data-src");
$(this).attr("src",url);
});
$("#main-content .article").find(".content").each(function(i,e){
$(this).attr("style","");
})
let content = $("#main-content .article").html();
let postdata = {
catid:data.catid,
title:data.title,
source_name:data.source_name,
thumb:thumb,
extra:data.extra || '',
content:content,
};
//postdata为最终采集数据,保存流程需自行实现
console.log(postdata);
}else{
console.log("无此分类"+data.cat_info);
}
}
//定时执行采集任务
let rule = new schedule.RecurrenceRule();
let times = [0,15,30,45];
rule.second = times;
schedule.scheduleJob(rule,()=>{
init();
})
至此,一个简单的爬虫应用就完成了,代码很简单,只是给大家提供一个思路,可以参考示例项目