修身洁行,言必由绳墨

用NodeJS的puppeteer做爬虫,抓取任何网页

2020.03.02

那些vue、react或是通过ajax请求数据来渲染的网页,我们抓取内容,一般也只能通过抓接口,但最近在抓取今日头条数据的时候,发现他们的接口需要token验证权限,瞬间懵逼了,研究了好长时间,是在找不出他们的加密规则,无奈只能另辟他境。

在通过多方面探索以后,总算让我找到了一个可行的方法,那就是用NodeJS的puppeteer来启动浏览器访问网页,然后在抓取执行完成后的网页。

Puppeteer

Puppeteer 是啥

Puppeteer是一个Node库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。Puppeteer 默认以 headless 模式运行,但是可以通过修改配置文件运行“有头”模式。

Puppeteer可以完成啥工作:

  • 访问页面,进行截图
  • 自动进行键盘输入,提交表单
  • 模拟点击等用户操作
  • 等等等等。。。
    更多功能,请看:Github Puppeteer

Puppeteer 抓取数据

废话少说,给大家做一个例子,抓掘金首页的连接,然后保存为Json数据

代码:

const puppeteer = require('puppeteer');
const fs = require('fs');

// 等待
const sleep = time => new Promise(resolve => {
     setTimeout(resolve, time);
});

const url = `https://juejin.im/`;

(async () => {
    // 启动一个浏览器
    const browser = await puppeteer.launch({
        headless: true,
        args: ['--no-sandbox']
    })
    // 开启一个新页面
    const page = await browser.newPage();
    // 增加请求头
    await page.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36');
    // 去掘金那个页面
    await page.goto(url, {
        waitUntil: 'networkidle2'  // 网络空闲说明已加载完毕
    });

    await sleep(3000); //等待3千毫秒执行

    //page.waitForNavigation({timeout: 480000})

    // 打印页面错误信息
    page.on('console', msg => {
      console.log('PAGE:', msg.text())
    })
    /* 截图
    await page.screenshot({path:'example.png'});
    */

    /* 拿整个body里面的内容保存
    await sleep(3000);
    const bodyHandle = await page.$('body');
    const html = await page.evaluate(body => body.innerHTML, bodyHandle);
    fs.writeFileSync('juejin.text',JSON.stringify(html));
    */

    /* 拿H5页面视频的播放地址
    const playerurl = await page.evaluate(() => {
        var $ = window.$;
        var url = $('video').attr('src');
        return url
    }); */
    

    // 抓取掘金首页内容保存为json
    await page.waitFor(1000);
    await page.evaluate(async () => {
        window.scrollTo(0,document.querySelector('.entry-list').scrollHeight);
    });
    await page.waitFor(500);
    await page.evaluate(async () => {
        window.scrollTo(0,document.querySelector('.entry-list').scrollHeight);
    });
    await page.waitFor(500);
    const res = await page.evaluate(async () => {
        window.scrollTo(0,document.querySelector('.entry-list').scrollHeight)
        window.scrollTo(0,document.querySelector('.entry-list').scrollHeight)
        return [].map.apply(document.querySelectorAll('.info-row.title-row .title'),[v => ({
            title:v.innerText,
            link:v.href,
        })])
    });
    // 将数据保存
    fs.writeFileSync('juejin.json',JSON.stringify(res));
    
    // 关闭浏览器
    browser.close();
})();

1、编辑保存为:juejin.js

2、linux或Mac控制台执行:/usr/local/node/bin/node juejin.js

3、执行后打开juejin.json,效果如下图
juejin_json.jpg

注意,一定要安装nodejs,要知道只是node的一个库,装node的方法自行搜索吧。

文章写到这里就完了,后续可能会对文章进行补充,可乐本人一直崇尚够用就好,所以是用到哪,就写到哪,至于Puppeteer其他的高级用法,大家自行去脑补吧。