Nodejs中puppeteer抓取浏览器HAR数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nodejs中puppeteer抓取浏览器HAR数据相关的知识,希望对你有一定的参考价值。

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

har.js

const puppeteer = require(‘puppeteer‘);
const PuppeteerHar = require(‘puppeteer-har‘);

/*
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  const har = new PuppeteerHar(page);
  await har.start({ path: ‘results.har‘ });

  await page.goto(‘http://example.com‘);

  await har.stop();
  await browser.close();
})();
*/

async function saveHarlog(url,filename){
  //启动浏览器实例 [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‘,
    //设置超时时间
    timeout: 15000,
    //如果是访问https页面 此属性会忽略https错误
    ignoreHTTPSErrors: true,
    // 关闭headless模式, 不会打开浏览器
    headless: false,
    args:["--disk-cache-size=0","--disable-cache",‘--disable-infobars‘],
    //是否为每个选项卡自动打开DevTools面板。 如果此选项为true,则headless选项将设置为false。
    devtools:false
  });
  //创建一个新页面
  let page = await browser.newPage();
  //Puppeteer 初始化的屏幕大小默认为 800px x 600px。但是这个尺寸可以通过 Page.setViewport() 设置。
  await page.setViewport({
        width: 800,
        height: 600
  });
  let har = new PuppeteerHar(page);
  await har.start({ path: (filename +‘.har‘) });
  await page.goto(url);

  // Get the "viewport" of the page, as reported by the page.
  let dimensions = await page.evaluate(() => {
    return {
      width: document.documentElement.clientWidth,
      height: document.documentElement.clientHeight,
      deviceScaleFactor: window.devicePixelRatio
    };
  });

  await har.stop();
  await browser.close();
}

exports.saveHarlog = saveHarlog;

cvsresovler.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;

main.js

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

const cvsresovler=require("./module/cvsresovler");
const mhar=require("./module/har");

/*
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

*/  
function init(){
        console.log(‘初始化调度器‘) ;
    //每分钟的第30秒定时执行一次:
    schedule.scheduleJob(‘0 21 * * * *‘,()=>{
        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(stats.isDirectory()){
                    isExist = false ;
                }
        }
        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‘] ;
            console.log("开始处理:" + url ) ;
            await mhar.saveHarlog(‘http://‘ + url,path.join(dirPath,url.replace(‘/‘,"-"))) ;
            if(i + 1 < dataArr.length){
                iterator(i+1) ;
            }
    })(0) ;
  }); 
  console.log(‘应用程序启动完成‘) ;
}
//执行
init();

以上是关于Nodejs中puppeteer抓取浏览器HAR数据的主要内容,如果未能解决你的问题,请参考以下文章

puppeteer + nodejs 抓取网页内容

如何使用 NodeJS 和 puppeteer 从 udemy 抓取图像

实例:使用puppeteer headless方式抓取JS网页

爬虫应用示例--puppeteer数据抓取的实现方法(续1)

Chrome Headless puppeteer CPU 过多

使用Puppeteer进行数据抓取——简单的示例