从零开始的Puppeteer(二)

453 阅读3分钟

Puppeteer数据提取

上一章已经和大家一起了解了Puppeteer,本章会和大家一起学习一下puppeteer简单的数据提取功能,以获取掘金沸点热门为例。

准备工作

node环境,vscode(或其他)

安装 Puppeteer

首先,需要使用 npm 或 yarn 安装 Puppeteer:

npm install puppeteer

或者

yarn add puppeteer

模拟登录

模拟登录分为:

  • 通过dom交互进行模拟真实登录
  • 通过写入cookie模拟已登录环境

模拟真实登录

通过Puppeteer提供的api来实现,主要有

page.waitForSelector(selector) //要等待的元素选择器
page.click(selector) //点击元素
page.type(selector,text) //要输入内容的元素选择器如果有多个匹配的元素,输入到第一个匹配的元素,要输入的内容

代码如下:

const puppeteer = require("puppeteer");
const cookieObjects = require('./cookie');
(async  () => {
  const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({ headless: false })
const page = await browser.newPage()
const navigationPromise = page.waitForNavigation()

await page.goto('https://juejin.cn/')

await page.setViewport({ width: 1745, height: 852 })

await page.waitForSelector('.nav-list > .right-side-nav > .nav-item > .login-button-wrap > .login-button')
await page.click('.nav-list > .right-side-nav > .nav-item > .login-button-wrap > .login-button')

await page.waitForSelector('.login-main > .panel > .input-group > .dropdown-box > .input')
await page.click('.login-main > .panel > .input-group > .dropdown-box > .input')

await page.waitForSelector('.auth-body > .login-body > .login-main > .other-login-box > .clickable')
await page.click('.auth-body > .login-body > .login-main > .other-login-box > .clickable')

await page.waitForSelector('.login-main > .panel > .input-group > .focus > .input')
await page.click('.login-main > .panel > .input-group > .focus > .input')

await page.type('.login-main > .panel > .input-group > .focus > .input', '1234567

await page.waitForSelector('.login-main > .panel > .input-group > .input-box > .login-password')
await page.click('.login-main > .panel > .input-group > .input-box > .login-password')

await page.type('.login-main > .panel > .input-group > .input-box > .login-password', '1234567

await page.waitForSelector('.auth-body > .login-body > .login-main > .panel > .btn')
await page.click('.auth-body > .login-body > .login-main > .panel > .btn')

await page.waitForSelector('#secsdk-captcha-drag-wrapper > .secsdk-captcha-drag-icon > .sc-kkGfuU > svg > path')
await page.click('#secsdk-captcha-drag-wrapper > .secsdk-captcha-drag-icon > .sc-kkGfuU > svg > path')

await navigationPromise
})()

运行:

image.png

Hadless Recorder

大家看到这里估计会吐槽写的好乱,其实这里是想和大家介绍一款工具Headless Recorder,在chrome插件记录你在网页上的操作并且自动生成puppeteer脚本,也可以通过github下载后执行npm i,npm run build然后在chrome浏览器安装即可。 安装好后可以通过点击红色按钮来进行录制,中间可以暂停,点击结束后该工具会生成脚本,点击Copy即可复制, 将生成好的脚本进行简单修改后即可运行。在设置选项里有ywright/puppeteer launch options可以取消勾选,这样每次生成的脚本会默认打开浏览器。

image.png

写入cookie模拟已登录环境

写入cookie模拟已登录环境是本人比较推荐的一种方式,用起来非常简单稳定,因为在使用交互方式时,很多场景下都会有验证码(后面会讲到)所以现在推荐大家使用cookie, Puppeteer设置cookie主要使用到了page.setCookie(cookie),注意这里的cookie格式要标准,这里推荐一款插件 EditThisCookie这里是他的github

image.png

将导出的标准cookie存放到单独文件中如:cookie.js,主代码如下:

const puppeteer = require("puppeteer");
const cookieObjects = require('./cookie');
(async  () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.setViewport({ width: 1280, height: 800 }); // 设置浏览器视窗大小

  cookieObjects.forEach((cookie) => {
      page.setCookie(cookie);
  });
  await page.goto("https://juejin.cn/pins");
})()

运行代码,打开后即是登录后的沸点

image.png

提取数据

现在已经打开沸点页面,可以使用Puppeteer提供的page.evaluate实现,代码如下:

const puppeteer = require("puppeteer");
const cookieObjects = require('./cookie');
(async  () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.setViewport({ width: 1280, height: 800 }); // 设置浏览器视窗大小

  cookieObjects.forEach((cookie) => {
      page.setCookie(cookie);
  });
  await page.goto("https://juejin.cn/pins");
  await page.waitForSelector("#juejin > div.view-container.pin_container > main > main > div.stream.no-topic-list.no-hot-new-tag > div.stream-wrapper > div.pin-list-view > div > ul > span > li");
  let pins = []
  pins = await page.evaluate((pins) => {
    const list = document.querySelectorAll('#juejin > div.view-container.pin_container > main > main > div.stream.no-topic-list.no-hot-new-tag > div.stream-wrapper > div.pin-list-view > div > ul > span > li')
    list.forEach(item => {
      console.log(item)
      pins.push({
        auth: item.querySelector('.username').innerText,
        content: item.querySelector('.content').innerText
      })
    })
    return pins
  }, pins)
  console.log('------------')
  console.log(pins)
})()


这样我们就能提取到沸点的数据。 image.png

github:github.com/puppeteer/p…