NodeJs和puppeteer结合的爬虫方案
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://linux.cn/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
赞 (0)