In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces "how to generate posters with Puppeteer library in Node". In daily operation, I believe many people have doubts about how to use Puppeteer library to generate posters in Node. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful to answer the questions of "how to generate posters with Puppeteer library in Node". Next, please follow the editor to study!
The previous article wrote that a few days ago, due to the use of html2canvas encountered a lot of compatibility problems, almost ran away with the bucket. Then, under the guidance of the bosses in the comment area, we found a poster generation scheme with simple operation and high reusability-Node+Puppeteer poster generation.
The main design idea is to access the interface that generates the poster, and the interface accesses the incoming address through Puppeteer, and returns the screenshot of the corresponding elements.
What are the advantages of Puppeteer generation posters over Canvas generation:
There are no browser compatibility, platform compatibility and other issues.
High code reusability, H6, Mini Program, app poster generation services can be used.
There is more room for optimization. Because it is changed to the form of interface to generate posters, various server-side ways can be used to optimize the response speed, such as adding servers and caching.
Puppeteer introduction
Puppeteer is a Nodejs library that provides a high-level API to control Chromium or Chrome through the DevTools protocol. Puppeteer runs in headless mode by default, which is called "headless" mode, but you can run "headless" mode by modifying the configuration of headless:false. Most of the operations performed manually in the browser can be done using Puppeteer! Here are some examples:
Generate a page PDF or screenshot.
Grab SPA (single page application) and generate pre-rendered content (that is, "SSR" (server-side rendering).
Automatically submit forms, conduct UI tests, keyboard input, etc.
Create an automated test environment that is constantly updated. Use the latest JavaScript and browser capabilities to perform tests directly in the latest version of Chrome.
Capture the timeline trace of a website to help analyze performance problems.
Test the browser extension.
Scheme realization
1. Write a simple interface
Express is a concise and flexible node.js Web application framework. Write a simple node service using express, define an interface, and pass the configuration items needed to receive the screenshot to puppeteer.
Const express = require ('express') const createError = require ("http-errors") const app = express () / / middleware-- json into the parameter app.use (express.json ()) app.post (' / api/getShareImg', (req, res) = > {/ / business logic}) / / error intercept app.use (function (req, res, next) {next (createError (404));}) App.use (function (err, req, res, next) {let result = {code: 0, msg: err.message, err: err.stack} res.status (err.status | | 500) .json (result)}) / / start service listening on port 7000 const server = app.listen (7000, '0.0.0.0, () = > {const host = server.address (). Address Const port = server.address () .port; console.log ('app start listening at http://%s:%s', host, port);})
two。 Create a screenshot module
Open a browser = > Open a tab = > Screenshot = > close the browser
Const puppeteer = require ("puppeteer"); module.exports = async (opt) = > {try {const browser = await puppeteer.launch (); const page = await browser.newPage (); await page.goto (opt.url, {waitUntil: ['networkidle0']}); await page.setViewport ({width: opt.width, height: opt.height,}) Const ele = await page.$ (opt.ele); const base64 = await ele.screenshot ({fullPage: false, omitBackground: true, encoding: 'base64'}); await browser.close (); return _' data:image/png;base64,'+ base64} catch (error) {throw error}}
Puppeteer.launch ([options]): launch a browser
Browser.newPage (): create a tab
Page.goto (url [, options]): navigate to a page
Page.setViewport (viewport): define the window that opens the page
Page.$ (selector): element selection
ElementHandle.screenshot ([options]): take screenshots. Where the encoding property can specify whether the return value is base64 or Buffer
Browser.close (): close browsers and tabs
3. Optimize
1. Request time optimization
The configuration item waitUntil of the page.goto (url [, options]) method indicates when the execution is completed. The default is when the load event is triggered. Events include:
Await page.goto (url, {waitUntil: ['load', / / page "load" event triggers' domcontentloaded', / / page "DOMcontentloaded" event triggers' networkidle0', / / there are no network connections in 500ms' networkidle2' / / the number of network connections in 500ms does not exceed 2]})
If the solution using networkidle0 waits for the page to be completed, you will find that the response time of the interface will be longer, because networkidle0 needs to wait for 500ms, and in many real business scenarios, you do not need to wait, so you can encapsulate a delay timer and customize the waiting time. For example, our poster page only renders a background image and a QR code image. When the page triggers load, it has already been loaded. There is no need for waiting time. You can pass 0 to skip the waiting time.
Const waitTime = (n) = > new Promise ((r) = > setTimeout (r, n)); / / omit some codes await page.goto (opt.url); await waitTime (opt.waitTime | | 0)
If this approach is not satisfied, you need the page to notify the end of the puppeteer at some point, and you can also use page.waitForSelector (selector [, options]) to wait for a specified element on the page to appear. For example, when the page finishes performing an operation, insert an element of id= "end", and puppereer waits for this element to appear.
Await page.waitForSelector ("# end")
Similar methods include:
Page.waitForXPath (xpath [, options]): wait for the element corresponding to xPath to appear on the page.
Page.waitForSelector (selector [, options]): wait for the matching element of the specified selector to appear on the page, and if there is already a matching element when this method is called, this method returns immediately.
Page.waitForResponse (urlOrPredicate [, options]): wait for the specified response to finish.
Page.waitForRequest (urlOrPredicate [, options]): wait for the specified response to appear.
Page.waitForFunction (pageFunction [, options [,... args]]): wait for a method to execute.
Page.waitFor (selectorOrFunctionOrTimeout [, options [,... args]]): this method is equivalent to the selector of the above methods. Depending on the result of the first parameter, for example, passing a string type will determine whether it is xpath or selector, which is equivalent to waitForXPath or waitForSelector.
two。 Startup item optimization
When Chromium starts, it also turns on a lot of unwanted functions, and you can disable some startup items through parameters.
Const browser = await puppeteer.launch ({headless: true, slowMo: 0, args: ['- no-zygote','--no-sandbox','--disable-gpu','--no-first-run','--single-process','--disable-extensions' "--disable-xss-auditor",'--disable-dev-shm-usage','--disable-popup-blocking','--disable-setuid-sandbox','--disable-accelerated-2d-canvas','--enable-features=NetworkService',]})
3. Reuse browser
Because every time the interface is called, a browser is launched, and the browser is closed after the screenshot, resulting in a waste of resources, and it takes time to start the browser. And if too many browsers are launched at the same time, the program will throw an exception. So the connection pool is used: launch multiple browsers, create a tab under one of the browsers to open the page, and only close the tab after the screenshot is completed, keeping the browser. When the next request comes, create a tab directly to achieve the purpose of reusing the browser. Close the browser when it is used a certain number of times or when it is not used for a period of time. Some bosses have dealt with the connection pool of generic-pool, so I used it directly.
Const initPuppeteerPool = () = > {if (global.pp) global.pp.drain () .then (() = > global.pp.clear ()) const opt = {max: 4 puppeteer instances / maximum number of puppeteer instances generated. Min: 1 the minimum number of puppeteer instances in the pool that survive testOnBorrow: true,//: the pool should validate instances before providing them to users. Autostart: does false,// need to initialize the instance during pool initialization idleTimeoutMillis: 1000 * 60 * 60 false,// / if an instance has not been accessed for 60 minutes, turn it off evictionRunIntervalMillis: 1000 * 60 * 3 dagger / check the access status of the instance every 3 minutes. MaxUses: 2048 * gamble / Custom attribute: maximum number of reusability of each instance. Validator: () = > Promise.resolve (true)} const factory = {create: () = > puppeteer.launch ({/ / Startup parameters refer to item 2}). Then (instance = > {instance.useCount = 0; return instance }), destroy: instance = > {instance.close ()} Validate: instance = > {return opt.validator (instance) .then (valid = > Promise.resolve (valid & & (opt.maxUses genericAcquire (). Then (instance = > {instance.useCount + = 1 return instance}) pool.use = fn = > {let resource return pool .acquire () .then (r = > {resource = r return resource}) .then (fn) .then (result = > { / / regardless of whether the business side uses the instance successfully or after, it indicates that the instance consumption is completed pool.release (resource) return result} Err = > {pool.release (resource) throw err})} return pool } global.pp = initPuppeteerPool ()
4. Optimize the interface to prevent repeated generation of pictures
When repeatedly called with the same set of parameters, a browser process is opened each time to take screenshots, and the caching mechanism can be used to optimize repeated requests. The image base64 can be stored in redis or written to memory by passing in a unique key as the identification bit (such as the user id+ activity id). When the interface is requested, check to see if it has been generated in the cache, and if so, directly from the cache. Otherwise, follow the process of generating posters.
At this point, the study on "how to generate posters with Puppeteer libraries in Node" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.