NodeJs和puppeteer结合的爬虫方案
由于对NodeJs的数据库操作是异步的,不是同步的,所以去重的方案,直接是删除之前添加的数据,在添加新的。
代码篇:const puppeteer = require('puppeteer');const mysql = require('mysql');const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '1234567890',
database: 'Demo'});(async () => {
try {
var timestamp = new Date();
var year = timestamp.getFullYear().toString();
var month = (timestamp.getMonth() + 1).toString();
var day = timestamp.getDate().toString();
var hours = timestamp.getHours().toString();
var m = timestamp.getMinutes().toString();
var s = timestamp.getSeconds().toString();
var dataRet = year + "-" + month + "-" + day + " " + hours + ":" + m + ":" + s;
const browser = await puppeteer.launch({
headless: true,
slowMo: 1000, //时间间隔
args: [
'–disable-gpu', // GPU硬件加速
'–disable-dev-shm-usage', // 创建临时文件共享内存
'–disable-setuid-sandbox', // uid沙盒
'–no-first-run', // 没有设置首页。在启动的时候,就会打开一个空白页面。
'–no-sandbox', // 沙盒模式
'–no-zygote',
'–single-process' // 单进程运行
]
})
const page = await browser.newPage();
// 需要抓取的网址
await page.goto("https:///news/secnews/", {
'timeout': 0 //无限大
});
// 先取14行数据 ,innerHTML取出html,innerText取出Text
// 首页数据
let bodyHandle = await page.evaluate(() => {
let list = [...document.querySelectorAll('.bm .block ul')];
return list.map((lt) => {
return {
title: lt.querySelector("li .title a").text,
url: lt.querySelector("li .title a").href,
banner: lt.querySelector("li .new img").src,
}
});
});
console.log("===首页采集成功===");
var arrayContent = [];
// 处理数据
for (var i = 1; i < bodyHandle.length; i++) {
var a = bodyHandle[i];
pageS = await browser.newPage();
await pageS.goto(a.url, {
'timeout': 0
});
console.log("完成个数:" + i);
let bodycontent = await pageS.evaluate(() => {
let author = document.querySelector('#article_copyright .textcut').innerText;
let article_date = document.querySelector('#article_copyright #article_date').innerText;
let article_content = document.querySelector('.d #article_content').innerHTML;
return {
author: author,
article_date: article_date,
article_content: article_content
}
});
arrayContent.push({
title: a.title,
banner: a.banner,
url: a.url,
bodycontent
});
};
console.log("===内容页采集成功===");
connection.connect();
// 简单粗暴的解决方案,直接删除,原因,nodejs操作MySQL是一个队列,导致产生脏数据
for (var j = 1; j < arrayContent.length; j++) {
var content = arrayContent[j];
var delSql = "delete from tb_news where url = ?";
var delSqlParams = [content.url];
// 删除
connection.query(delSql, delSqlParams, function (err, delresult) {
if (err) {
console.log('[INSERT ERROR] - ', err.message);
return;
}
console.log('DELETE affectedRows', delresult.affectedRows);
});
}
// 添加
for (var h = 1; h < arrayContent.length; h++) {
var content = arrayContent[h];
var addSql = "INSERT INTO tb_news(title,banner,url,author,content,article_date) VALUE(?,?,?,?,?,?)";
var addSqlParams = [content.title, content.banner, content.url, content.bodycontent.author, content.bodycontent.article_content, dataRet];
// 增
connection.query(addSql, addSqlParams, function (err, result) {
if (err) {
console.log('[INSERT ERROR] - ', err.message);
return;
}
console.log('INSERT ID:', result.insertId);
});
}
console.log('===数据处理成功===');
connection.end();
browser.close();
} catch (err) {
console.log(`this is the ${err}`);
}})();
后期会持续集成钉钉,作为消息通知,作为每次爬虫执行结果的通知。
结果:
╰$ node 51CTO.js
===首页采集成功===
完成个数:1
完成个数:2
完成个数:3
完成个数:4
完成个数:5
完成个数:6
完成个数:7
完成个数:8
完成个数:9
完成个数:10
完成个数:11
完成个数:12
完成个数:13
完成个数:14
===内容页采集成功===
===数据处理成功===
DELETE affectedRows 1
DELETE affectedRows 1
DELETE affectedRows 1
DELETE affectedRows 1
DELETE affectedRows 1
DELETE affectedRows 1
DELETE affectedRows 1
DELETE affectedRows 1
DELETE affectedRows 1
DELETE affectedRows 1
DELETE affectedRows 1
DELETE affectedRows 1
DELETE affectedRows 1
INSERT ID: 26
INSERT ID: 27
INSERT ID: 28
INSERT ID: 29
INSERT ID: 30
INSERT ID: 31
INSERT ID: 32
INSERT ID: 33
INSERT ID: 34
INSERT ID: 35
INSERT ID: 36
INSERT ID: 37
INSERT ID: 38
|