你知道 FaaS 还能用 Puppeteer 吗?

背景

笔者最近在做个小工具,需要爬一些数据。这种场景显然用 FaaS 是最划算的,于是有了这篇《不用爬虫,用 FaaS 来获取股票期权数据》。

有些数据没法通过接口直接获得,必须得爬网页的数据,然后从页面里读数据。这个也还好说,只要能够爬到页面的源代码,然后在本地用 cheerio 之类的库解一下,然后像用 jQuery 一样读取想要的元素即可。

但是,最近碰到了个新问题。有的数据是需要登录后才能展示全的,也就是说爬数据的时候需要带上 cookie。登录接口又做了加密算法,没法直接调接口。这种情况要怎么办呢?

嘿嘿,当然难不倒我这个老司机了。我们有 Puppeteer(以下简称 pptr)啊,有了 pptr,任何场景都难不倒我们。

不知道 pptr 的同学可以自己查一下,简单说就是一个 headless 浏览器,理论上我们可以用它模拟任何人为操作,比如点点点,敲敲敲,划划划。

那么问题来了,FaaS 里面能用 pptr 吗?答案当然是肯定的,要不我写这篇干什么

正文

新建 pptr 函数

这里以阿里云的「函数计算 FC」为例。有 2 种方法:

第一种是按照它给的模板(强烈推荐),直接生成有 pptr 的函数。

你知道 FaaS 还能用 Puppeteer 吗?

第二种是自己创建,然后给函数加个 pptr 的层。还需要注意版本是否匹配,很麻烦的(别问我怎么知道的)。

你知道 FaaS 还能用 Puppeteer 吗?

这里我们只说第一种。创建完函数之后,它会有个示例代码,很清晰(就是这 ES6 和 ES5 混用的语法……):

'use strict';
const puppeteer = require('puppeteer');

function autoScroll(page) {
  return page.evaluate(() => {
      return new Promise((resolve, reject) => {
          var totalHeight = 0;
          var distance = 100;
          var timer = setInterval(() => {
              var scrollHeight = document.body.scrollHeight;
              window.scrollBy(0, distance);
              totalHeight += distance;
              if (totalHeight >= scrollHeight) {
                  clearInterval(timer);
                  resolve();
              }
          }, 100);
      })
  });
}

exports.handler = (event, context, callback) => {
  (async () => {
    const browser = await puppeteer.launch({
      headless: true,
      args: [
        '--disable-gpu',
        '--disable-dev-shm-usage',
        '--disable-setuid-sandbox',
        '--no-first-run',
        '--no-zygote',
        '--no-sandbox',
        '--single-process'
      ]
    });

    let url = 'https://www.serverless-devs.com';
    const page = await browser.newPage();
    await page.emulateTimezone('Asia/Shanghai');
    await page.goto(url, {
      'waitUntil': 'networkidle2'
    });
    await page.setViewport({
      width: 1200,
      height: 800
    });
    await autoScroll(page)
    let path = '/tmp/example';
    await page.screenshot({ path: path, fullPage: true, type: 'png' });
    await browser.close();
    callback(null, "success!")
  })().catch(err => {
    callback(err.message, null);
  });
}

直接点击「测试函数」就能看到效果了。这里要强调一下,puppeteer.launch 方法里的 args 参数,一定要写全了,否则极大可能会报错。

代码实现

好了,接下来就是实现我们自己的登录逻辑了。其实到了这里就没什么难度了,直接上代码:

'use strict';
const puppeteer = require('puppeteer');

const getJiSiLuCookie = async () => {
  const browser = await puppeteer.launch({
    headless: true,
    args: [
      '--disable-gpu',
      '--disable-dev-shm-usage',
      '--disable-setuid-sandbox',
      '--no-first-run',
      '--no-zygote',
      '--no-sandbox'
    ]
  });
  const page = await browser.newPage();
  await page.goto('https://www.jisilu.cn/account/login/');
  await page.waitForSelector('input[name=user_name]');
  await page.type('input[name=user_name]', 'your user name');
  await page.type('input[name=password]', 'your password');
  await page.click('.user_agree input[type=checkbox]');
  await page.click('.btn-jisilu');
  await page.waitForNavigation({ waitUntil: 'networkidle2' });
  const cookie = await page.evaluate(() => document.cookie);
  await browser.close();
  return cookie;
};

exports.handler = async (event, context, callback) => {
  try {
    const cookie = await getJiSiLuCookie();
    callback(null, cookie);
  } catch (e) {
    console.log(e);
    callback(e, null)
  }
}

这里用的是登录 集思录 的例子,好在它不需要验证码,如果需要验证码,那就是另一个故事了。大概需要用到截屏和存储,我们以后再聊。

更多 pptr 调试开发的技巧,可以看这一篇《如何用 puppeteer 爬取「飞书」wiki 知识库文档的数据?》,相信我,看完你一定会有收获。

结语

FaaS 是各大云厂商都有的服务,只不过叫的名字不同。对于小流量的场景来说,比买一个服务器划算多了。

说实话,之前真没想到 FaaS 里面竟然能用 pptr。直到碰到问题之后一查才发现,纳尼?!这么高级,这么方便了吗?

云计算其实没有多数人想的那么神秘,只要自己工程方面的基本功扎实,这些服务用起来真的很方便,很顺手,也很经济。推荐大家多多关注,学习和应用哦。

PS:最近整理电脑,才想起来之前在腾讯云工作的时候,还考了个腾讯云架构师的证书,哈哈,赶紧加到简历里。

原文链接:https://juejin.cn/post/7325728181247606821 作者:DylanlZhao

(0)
上一篇 2024年1月20日 下午5:07
下一篇 2024年1月21日 上午10:00

相关推荐

发表回复

登录后才能评论