Nodejs中puppeteer通过Event抓取HAR数据

有这么一个需求,首先从cvs文件中读取要解析的url数据,然后使用puppeteer和puppeteer-har来获取浏览器的HAR数据。在调试的过程中,发现在for循环中怎么操作都是异步的,最后找到了一个解决方案,也算在此记录。

1,创建解析csv文件的代码(ultra-harlog/module/cvsresovle.js)

const fs = require("fs");
const path = require("path");
const csv =require('csv');
const parse = require('csv-parse/lib/sync')
const iconv = require('iconv-lite');   

/*
npm install iconv-lite 
*/
function readUrlRecord(csvpath){
    console.log('开始解析文件:' + csvpath) ;

    //读取文件
    const input = fs.readFileSync(csvpath,'utf8') ;

    /*
    解析文件,生成JSON格式

    { '   ': '142',
    AREA_NAME: '湖北',
    SITE_LINK: 'www.banggo.com',
    BEARING_MODE: '移动接入',
    SITE_NAME: '邦购',
    MENU_TYPE: '二级' }

    */
    const records = parse(input, {
      columns: true,
      skip_empty_lines: true,
      delimiter: ',',
    }) ;

    return records ;
}

//readUrlRecord('../top300.csv') ;

exports.readUrlRecord = readUrlRecord;

2,创建抓取主代码(ultra-harlog/module/puppeteerhar-event.js)

const fs = require('fs');
const { promisify } = require('util');
const path = require("path");

const puppeteer = require('puppeteer');
const { harFromMessages } = require('chrome-har');

const logger=require("./log");

const log = logger.getPuppeteerHarEventRecordLogger() ;

//https://michaljanaszek.com/blog/generate-har-with-puppeteer
//https://www.npmjs.com/package/chrome-har

// 设置要监控的事件
const observe = [
  'Page.loadEventFired',
  'Page.domContentEventFired',
  'Page.frameStartedLoading',
  'Page.frameAttached',
  'Network.requestWillBeSent',
  'Network.requestServedFromCache',
  'Network.dataReceived',
  'Network.responseReceived',
  'Network.resourceChangedPriority',
  'Network.loadingFinished',
  'Network.loadingFailed',
];

/*
    启动浏览器
*/ 
async function launchBrowser(){
    //启动浏览器实例 [puppeteer.createBrowserFetcher([options])]
  let browser = await puppeteer.launch({
    // 若是手动下载的chromium需要指定chromium地址, 默认引用地址为 /项目目录/node_modules/puppeteer/.local-chromium/
    //executablePath: '/Users/huqiyang/Documents/project/z/chromium/Chromium.app/Contents/MacOS/Chromium',
    //如果是访问https页面 此属性会忽略https错误
    ignoreHTTPSErrors: true,
    // 关闭headless模式, 不会打开浏览器
    headless: true,
    //浏览器启动参数 https://peter.sh/experiments/chromium-command-line-switches/   --timeout
    args:["--disk-cache-size=0","--disable-cache",'--disable-infobars','--window-size=800,600','--ignore-certificate-errors','--enable-feaures'],
    //是否为每个选项卡自动打开DevTools面板。 如果此选项为true,则headless选项将设置为false。
    devtools: false,
    //Defaults to 30000 (30 seconds). Pass 0 to disable timeout.
    timeout: 0
    //放慢puppeteer执行的动作,方便调试
    //slowMo: 250
  });
  return browser ;
}

async function saveHarlog(url,dirPath,filename){
    let homesite = url ;
    //保存的文件路径
    let harFilePath = path.join(dirPath,filename) ;
    //处理URL
    if(!(url.startsWith('http://') || url.startsWith('https://'))){
        url = "http://" + url ;
    }
  //打开浏览器
  let browser = await launchBrowser() ;

  //创建一个新页面
  //let page = await browser.newPage();
  let page = (await browser.pages())[0];

  // 注册事件监听器
  const client = await page.target().createCDPSession();
  await client.send('Page.enable');
  await client.send('Network.enable');

  //用于保存用于转为为HAR数据的事件
    const events = [];
  observe.forEach(method => {
    client.on(method, params => {
      events.push({ method, params });
    });
  });

  try{
    // 执行跳转,访问制定的资源
    await page.goto(url,{
            timeout:0
    });
  }catch(error){
    log.info('resovle error :' + url + ";  error message:" + error) ;
  }finally{
    if(browser){
        await browser.close();      
    }
  }
  const har = harFromMessages(events);
  //resovleHar(har) ;
  //log.info(JSON.stringify(har));

  await promisify(fs.writeFile)(harFilePath, JSON.stringify(har));
}

exports.launchBrowser = launchBrowser;
exports.saveHarlog = saveHarlog;

3,创建启动文件(ultra-harlog/puppeteerhar-event-app.js)

const fs = require("fs");
const path = require("path");
const moment = require("moment");
const schedule = require('node-schedule');

const cvsresovler=require("./module/cvsresovle");
const mhar=require("./module/puppeteerhar-event");

/*
cnpm install --save moment
cnpm install --save csv
cnpm install --save node-schedule
cnpm install --save puppeteer
cnpm install --save puppeteer-har
cnpm install --save iconv-lite
cnpm install --save chrome-har

cnpm install --save grpc
*/  
function init(){
        console.log('初始化调度器') ;
    //每分钟的第30秒定时执行一次:
    schedule.scheduleJob('0 55 8 * * *',()=>{
        let ftime = moment().format('YYYYMMDDHHmm');
        console.log('当前调度时间为:' + ftime) ;
        let dirPath = path.join(__dirname,'harlogs',ftime) ;
        console.log("创建目录:" + dirPath) ;

        let isExist = false ;
        if(fs.existsSync(dirPath)){
                //创建文件夹
                let stat = fs.lstatSync(dirPath);
                if(stat.isDirectory()){
                    isExist = true ;
                }
        }
        if(!isExist){
            //创建文件夹
            console.log("创建文件夹" + ftime) ;
                fs.mkdirSync(dirPath);
        }       
        //开始解析需要处理的URL
        let dataArr = cvsresovler.readUrlRecord(path.join(__dirname,'top300.csv')) ;
        console.log("解析出URL共计" + dataArr.length + "条") ;

        /*
            开始抓取HAR数据【同步的方式执行】。
            注意:如果这里直接通过for循环遍历dataArr并调用saveHarlog方法,那么这将是一个异步的过程。
        */
            (async function iterator(i){
                    let data =  dataArr[i]
                    let url = data['SITE_LINK'] ;

                url = url.trim() ;
                let filename = url.replace(/\//g,'-').replace(/\\/g,'-') + '.har' ;
                if(url){
                            console.log((i+1) + "-starting to resovle url :" + url ) ;
                    try{
                                await mhar.saveHarlog(url,dirPath,"N" + "-" + filename) ;
                            }catch(error){
                                console.log(error) ;
                            }
                }
                if(i + 1 < dataArr.length){
                    iterator(i+1) ;
                }
            })(0) ;
    }); 
    console.log('应用程序启动完成') ;
}

//执行
init();

/**
    用于测试的方法
*/
async function test(){
        let ftime = moment().format('YYYYMMDDHHmm');
    console.log('当前执行时间为:' + ftime) ;
    let dirPath = path.join(__dirname,'harlogs',ftime) ;
    console.log("创建目录:" + dirPath) ;

    let isExist = false ;
    if(fs.existsSync(dirPath)){
            //创建文件夹
            let stat = fs.lstatSync(dirPath);
            if(stat.isDirectory()){
                isExist = true ;
            }
    }
    if(!isExist){
        //创建文件夹
        console.log("创建文件夹" + ftime) ;
          fs.mkdirSync(dirPath);
    }     

    //测试的URL
        let url = "www.baidu.com" ; 

        let arguments = process.argv.splice(2);
        if(arguments.length > 0 ){
            url = arguments[0] ;
        }
        url = url.trim() ;

      let filename = url.replace(/\//g,'-').replace(/\\/g,'-') ;
        if(url){
            if(!(url.startsWith('http://') || url.startsWith('https://'))){
                url = "http://" + url ;
            }
            console.log("starting to resovle  test url :" + url ) ;

            try{
                await mhar.saveHarlog(url,dirPath,"NT" + "-" + filename) ;
            }catch(error){
                console.log(error) ;
            }
        }
}
//运行测试
//test() ;

转载于:https://blog.51cto.com/dengshuangfu/2365190

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
nodejs使用puppeteer是通过调用puppeteer库来实现的。Puppeteer是一个基于Chrome浏览器内核的nodejs爬虫包,它可以模拟用户操作界面,包括页面滚动、按钮点击、导航跳转等功能。你可以通过以下步骤来实现nodejs使用puppeteer: 1. 首先,安装puppeteer库。你可以通过全局安装或者当前项目安装的方式进行安装。全局安装的命令是:npm -g install puppeteer;当前项目安装的命令是:npm -S install puppeteer。 2. 创建一个async函数,例如puppeteerTest,在函数内部进行puppeteer操作。 3. 在puppeteerTest函数,你可以设置一些选项,例如设置用户代理(user agent),可以通过args参数来传递。例如,你可以设置options对象,其headless属性用于控制是否以无头模式运行,args属性用于设置命令行参数,包括设置用户代理。 4. 使用require语句引入puppeteer库,并通过puppeteer.launch(options)方法来启动一个浏览器实例。 5. 调用browser.newPage()方法创建一个新的页面实例。 6. 可以使用page.setViewport()方法设置页面的视口大小。 7. 使用page.goto(url)方法跳转到指定的URL地址。 下面是一个示例代码: ```javascript const puppeteerTest = async () => { const user_agent = "--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36"; const options = { headless: false, // 是否以无头模式运行 args: ['--no-sandbox', user_agent] // 设置命令行参数,包括设置用户代理 }; const puppeteer = require('puppeteer'); const browser = await puppeteer.launch(options); const page = await browser.newPage(); await page.setViewport({ width: 1020, height: 900 }); // 设置页面视口大小 await page.goto("https://www.baidu.com"); // 跳转到指定的URL地址 }; puppeteerTest(); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值