Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Puppeteer 批量自动生成并保存二维码 #54

Closed
Dream4ever opened this issue Jul 12, 2018 · 2 comments
Closed

Puppeteer 批量自动生成并保存二维码 #54

Dream4ever opened this issue Jul 12, 2018 · 2 comments
Labels
Front-end Everything you see and experience JS Javascript

Comments

@Dream4ever
Copy link
Owner

Dream4ever commented Jul 12, 2018

需求描述

出于业务需要,经常要批量生成二维码。之前都是上 草料二维码 这个网站,手动生成一堆二维码,效率低,容易出错。每次做这件事的时候,都是一边生成二维码,一边在想:怎样能把这个操作自动化了呢?

方案调研

想起来之前在 GitHub 上看过一个项目,好像是什么无头浏览器(headless browser),查了查自己的 GitHub 收藏列表,果然找到了,就是 GoogleChrome/puppeteer 这个项目。

应用过程

流程梳理

梳理了一下生成二维码的一系列操作,分为以下几个步骤:

  1. 打开 草料网址二维码生成器 这个页面
  2. 等待页面加载完毕
  3. 在文本框中输入需要生成二维码的网址
  4. 点击按钮『生成二维码』
  5. 等待页面自动跳转
  6. 下载页面中显示的二维码图片

这么一看,整个流程是不是很简单?的确如此,不过里面有一个大坑,后面会讲到。

代码实战

打开页面

首先试试用 puppeteer 打开网页并截图,这个在项目官网上是有现成的代码的:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://cli.im/url');
  await page.screenshot({
    path: 'cli.png'
  });

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

执行代码之后,查看生成的截图,虽然把网页截下来了,但是页面排版都错位了,有些内容没有显示出来。

01

参考资料:

查看官方文档,说页面尺寸默认设置为 800px * 600px,如果需要改变这个尺寸,就要用 Page.setViewport() 这个方法。在 Chrome 中打开空白标签页,查看页面尺寸为 1920px * 935px,那就设置成这个尺寸吧。

  ...
  await page.goto('https://cli.im/url');
  await page.setViewport({
    width: 1920,
    height: 935,
  });
  await page.screenshot({
    path: 'cli.png'
  });
  ...

这回再查看生成的截图,嗯,网页内容完整显示了,那就继续下一步。

02

参考资料:

文本框输入内容

页面加载完成之后,就需要在文本框中输入需要生成二维码的网址了。虽然在上一步的操作中,截图显示页面的内容都加载完成了。但是保险起见,还是需要等待文本框确实可用之后,再输入内容。

那么就需要先调用 page.waitForSelector() 这个方法,等待元素加载完毕。然后再调用 page.type() 方法,在文本框中输入网址:

  ...
  // 文本框元素的 id 属性值为 url_content
  await page.waitForSelector('#url_content');
  await page.type(
    '#url_content',
    'http://www.baidu.com/', {
    delay: 50,
  });

执行代码,查看生成的截图,嗯,文本框中成功输入内容了,继续下一步。

03

参考资料:

点击按钮生成二维码

接下来就该模拟点击按钮的操作,让网页生成二维码了。这个操作,用 page.click() 就可以实现了。

这里要和上一步一样,等待按钮确实可用之后,再去点击它。

  ...
  await page.waitForSelector('#click-create');
  await page.click('#click-create', {
    delay: 50,
  });

查看这一步操作完成后的截图,会发现页面停在“正在生成二维码”这里了,本应显示二维码图片的区域,显示的是一个表示“加载中”的图片,这是什么情况?

在浏览器中执行同样的操作,发现点击按钮之后,网站会跳转到新的页面,然后在新的页面上显示二维码。猜测 puppeteer 本身并不会自动跟随页面的跳转,那该怎么办咧?

上网用 puppeteer follow redirectpuppeteer 自动跳转 之类的关键字搜索,都没有找到可用的结果。

于是又去翻官方 API 文档,看了看文档左侧的分类列表,觉得这个功能应该归在 Page 这个类的下面,于是就挨个浏览这个类提供的方法,咦,page.waitForNavigation() 这个方法很可能就是正在找的东西,把它加到代码里试试看。

   ...
  await page.waitForNavigation();

05

啊哈,就是它了!这回可以看到生成的二维码了。其实之前自己在写代码的时候并没有这么顺利,差不多花了半天的时间才定位到问题的原因,真是台上一分钟,台下十年功呐。

参考资料:

下载二维码图片

终于到了最后一步了:下载二维码图片。先用 Chrome 的开发者工具查看图片这个元素的信息,能够看到这个元素的 idqrimage,并且用 document.querySelector('#qrimage') 这条语句确定了当前页面中没有重复 id 的元素。

那么,就根据 SAVING IMAGES FROM A HEADLESS BROWSER 这篇文章中的方法,将图片保存至本地。

  const qrcode = await page.$('#qrimage');
  await qrcode.screenshot({
    path: 'screenshot.png',
  });

在本机查看生成的截图,啊哈,保存成功!

为了确保代码没有问题,再用 草料二维码扫描器 检查刚才生成的二维码,嗯,的确没问题,大功告成!

参考资料:

二维码批量生成及下载

照着前面的方法一步步操作,已经可以把二维码图片下载到本地了。但是,研究前面这些内容,最终是为了实现二维码批量生成及下载。

查看前面『流程梳理』这一小节的内容,再思考二维码批量生成及下载的整个流程,可以确定,每一次生成二维码的过程,会有变化的,只是输入的网址,和保存至本地的图片的文件名。

这样一来,只需要在上面的代码外面套一层循环,每次在循环体中传入网址和图片文件名这两个变量,就可以满足自己的需求了。而且因为需要批量生成的文件名是很规则的,所以这个实现起来也很简单。

未完待续……

@Dream4ever Dream4ever added Front-end Everything you see and experience JS Javascript labels Jul 12, 2018
@hengmyj
Copy link

hengmyj commented Aug 2, 2018

very goods! think you

@Dream4ever
Copy link
Owner Author

@hengmyj 给我的项目点个 star 吧!哈哈。

@Dream4ever Dream4ever changed the title Puppeteer 实现浏览器自动化操作 Puppeteer 批量自动生成并保存二维码 Aug 5, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Front-end Everything you see and experience JS Javascript
Projects
None yet
Development

No branches or pull requests

2 participants