使用Puppeteer进行数据抓取(三)

722 阅读3分钟

前言

       基于上一篇文章,趁着公司业务不忙的时候,又悄悄跑过来更新文章,这回我们要讲到关于爬取的数据存储问题了。

必要依赖安装

1. mysql   (数据库的,相信各位小伙伴一定不会陌生)

npm install mysql

2.co-mysql  (将mysql中异步回调形式,令其可以使用async await形式)

 npm install co-mysql

基本配置实现之数据库简单配置

       说到数据库,我们首先想到是的登录数据库的一些必要东西,所以下面来讲讲关于数据库的部分小配置。首先我们新建一个config.js。(下面的代码不懂得话,可能要各位自行度娘了。)

const mysql = require('mysql');
var host = 'localhost';
var ip = 'http://127.0.0.1:3000'
var pool = mysql.createPool({    
   host: '127.0.0.1',    
   user: 'root',    
   password: 'XXXXX',  //这里的密码根据你们的数据库自行设置    
   database: 'personal-db',    
   connectTimeout: 30000})
module.exports = {    
   ip: ip,    
   pool: pool,    
   host: host,
}

代码逻辑实现

1.首先,我们要开始讲讲代码了,其实也很简单。我们接下去走走看看。

const mysql = require('./config');  // 引入我们的config文件
const wrapper = require('co-mysql') 
let db = wrapper(mysql.pool);  // 这里使用co-mysql 链接起我们的数据库

2. 其次 这个是mysql 插入数据库的语句

let addSql = 'INSERT INTO finance SET ?'

        可能很多小伙伴会说,为什么我的sql 总是提示语法错误。我是根据 菜鸟教程上面写的。 问题来了,这个还真不是菜鸟教程写错了,因为目前我们安装的版本是最新的,所以语法会有些许不一样。

低版本写法(引用 ‘www.runoob.com/nodejs/node…’) 有sql基础条件的同学可以跳过。

var  addSql = 'INSERT INTO websites(Id,name,url,alexa,country) VALUES(0,?,?,?,?)';

我们自己可以参考 (www.npmjs.com/package/mys…) 这是最新文档的地方,具体如下图。

3. 在代码的实现中

// addSql 是我们上面写的sql语句  obj是我们要存入的数据
 await db.query(addSql, obj).catch(err => { 
              console.log(err);
      })
// 就这么几行代码就实现了我们的具体功能了。

代码全部实现 

1.修复了上一篇文章部分小问题    (

const puppeteer = require('puppeteer')
const baseUrl = 'https://www.yicai.com';
const mysql = require('./config');
const wrapper = require('co-mysql')
let db = wrapper(mysql.pool);
let addSql = 'INSERT INTO finance SET ?'// 等待3000毫秒
const sleep = time => new Promise(resolve => {
    setTimeout(resolve, time);})
    ; (async () => {
        const browser = await puppeteer.launch({
            headless: false, //浏览器界面启动
            slowMo: 200,   //放慢浏览器执行速度,方便测试观察
            args: ['--no-sandbox'],
            dumpio: false,
            devtools: true, //开发模式
        });
        const page = await browser.newPage();
        await page.goto(baseUrl, {
            waitUntil: 'networkidle2'
        });        //由于出现了广告页面,从而影响到点击事件,所以先等待广告页面出现后将其关闭        await page.$eval('.m-layer',            (el, value) => el.setAttribute('style', value),            'display: none'        )        await page.waitFor(2000)        // 等待某个节点的加载
        await page.waitForSelector('.u-btn')
        for (let index = 0; index < 1; index++) {
            await page.waitFor(2000);
            await page.click('.u-btn')
        }
        const result = await page.evaluate(() => {
            let apiUrl = 'https://www.yicai.com';
            let $ = window.$;
            // var items = $('.m-con a')  //  不可用这个,由于页面是通过display:none or block来控制的,爬取的数据会是多个页面的叠加            var items = $('#headlist').children('a')
            var links = []
            if (items.length >= 1) {
                items.each((index, item) => {
                    let it = $(item)
                    let articleTitle = it.find('h2').text()
                    let articleIntroduction = it.find('p').text()
                    let imageAddress = it.find('img').attr('src')
                    let createdTime = it.find('span').text()
                    let detailPage = it.attr('href')
                    links.push({
                        articleTitle,
                        articleIntroduction,
                        imageAddress,
                        createdTime,
                        detailPage: apiUrl + detailPage 
                   })
                })
            }
            return links
        })
        // 暂缓1s
        await sleep(1000)
            ; (async () => {
                let allResult = []
                for (let i = 0; i < result.length; i++) {
                    let detailInfo = '';// 文章详情
                    await page.goto(result[i].detailPage, {
                        waitUntil: 'networkidle2'
                    });
                    // 先判断元素是否存在
                    const element = await page.$(".m-text");
                    if (element) {
                        await page.waitForSelector('.m-text')
                    }
                    var obj = await page.evaluate((result, i) => {
                        let $ = window.$; 
                       if ($("#multi-text").length > 0) {
                            var pageDom = $('#multi-text')
                            if (pageDom) {
                                detailInfo = pageDom[0].innerHTML
                            }
                            result[i].detailInfo = detailInfo
                            return obj = result[i]
                        } else {
                            result[i].detailInfo = ''
                            return obj = result[i]
                        }
                    }, result, i)
                    await db.query(addSql, obj).catch(err => {
                        console.log(err);
                    })
                    allResult.push(obj)
                    await page.waitFor(2000);
                    await page.goBack();
                }
                console.log(JSON.stringify(allResult))
                await page.close();
                // ------------------------------------------------------------------------------ 
               // 专页测试模块 
               // await page.goto('https://www.yicai.com/image/100730324.html', {
                //     waitUntil: 'networkidle2'
                // });
                // const element = await page.$(".m-text");
                // if (element) {
                //     await page.waitForSelector('.m-text')
                // }
                // var obj = await page.evaluate(() => {
                //     let obj = {}
                //     let $ = window.$;
                //     if ($("#multi-text").length > 0) {
                //         var pageDom = $('#multi-text')
                //         if (pageDom) {
                //             console.log('11111111111111')
                //             // https://www.yicai.com/video/100728928.html
                //             // https://www.yicai.com/image/100730324.html
                //             detailInfo = pageDom[0].innerHTML
                //         }else{
                //             console.log('222222222222222')
                //         }
                //     }
                // })
                // ------------------------------------------------------------------------------
            })();
    })();

2.实现截图,不弄虚作假。老实本分ing~

写在最后

编写文章只是用于学习,各位小伙伴也要老实本分哦。文章存在许多不足之处,希望路过的小伙伴多加指点,共同进步。