分享

NodeJs和puppeteer结合的爬虫方案

 雨夜的博客 2021-04-16

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

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多