puppeteer 学习笔记

因为 OI 学不下去了,所以整天搞一些小玩意。

安装

首先安装 node.js、node.exe,配置好环境变量等之后进行以下操作:

在工作目录下执行:

npm install express -g
npm install puppeteer

然后每次在当前目录中执行

node xxx.js [$value]

即可执行。

使用

python 爬虫可以拿下多数情况下的爬虫操作,但遇到动态 js 之类的玩意就不太行了。

这个时候 puppeteer 的模拟浏览器行为可以解决这个问题。py 也有类似的东西,但是有谷歌官方做支持的 puppeteer 的 bug 等会少一些。

0.实例创建与基本操作

我们可以通过以下代码创建一个实例:

const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({headless: false}); 
	// true 为不观看操作过程
	// executablePath: "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"
const page = await browser.newPage();
await page.goto(Url, {timeout: 0, waitUntil: 'load'});
await browser.close() // 关闭浏览器

page 有如下常用操作:

await page.goto(url); // 前往某个 url
await page.reload(); // 刷新
cookies=[{/*something*/},{...}];
await page.setCookie(...cookies); // 设置cookies,注意格式
await page.close(); //关闭当前页
await page.waitForTimeout(/*Time (ms)*/);
await page.waitForSelector('selector');
await page.waitForXpath('xpath');
await page.waitForNavigation(); // 等待页面完全加载完成。

有时 cmd 命令中需要传入一些参数,可以直接带在 .js 文件后面。

const value = process.argv[2]; // 2 为取出 .js 后第一项
/*
如: node test.js https://www.baidu.com
那么将取出 https://www.baidu.com	
*/
console.log(value) // 输出在标准输出中

数字代表项数,用空格分开。

更多操作见官方文档.许多 js 基本操作与 c++ 类似甚至完全一样。

1.获取页面元素

可以通过 selector 或 xpath 获取元素。

const element = await page.$eval('selector', el => el.something);
const value = await page.$x('xpath');
await value[0].click();

这将获取整个元素,具体要取出哪些内容要自己选择。select 便于获得一些 href 之类的玩意,xpath 则被我用于点击。
xpath获取的元素有若干属性,可通过通配符获取子节点个数:

const ele = await page.$x('//*[@id="comicContain"]/*');
const len = ele.length;

2.输入/点击/截图

实时获取命令行输入需要引入 readline-sync 库。

输入与点击操作:

await (await page.$x('xpath'))[0].type(something_to_type); // 通过某个xpath获取元素并输入
await (await page.$x('xpath'))[0].click(); // 选择元素并点击
await page.keyboard.press('[option]');	// 按一下
await page.keyboard.down('[option]');	// 按着
await page.keyboard.up('[option]');		// 松开

有时需要对某个元素截图并保存,可以通过以下代码实现:

async function screenshotDOMElement(page, selector, path, padding = 0) {
    const rect = await page.evaluate(selector => {
        try{
            const element = document.querySelector(selector);
            const {x, y, width, height} = element.getBoundingClientRect();
            if(width * height != 0){
                return {left: x, top: y, width, height, id: element.id}; }
            else { return null; }
        }catch(e){return null; }
    }, selector);
    return await page.screenshot({path: path, clip: rect ? {x: rect.left - padding, y: rect.top - padding, width: rect.width + padding * 2, height: rect.height + padding * 2 } : null });
}
// 传入: page实例、selector选择器、path保存路径. 

获得交互的方法如下:

var v_type = readlineSync.question('Some Output with the question');

那么 v_type 中就获得了实时的输入。

3.文件下载\保存

文件系统相关操作需要引入 fs 库。

文件路径相关操作则需要引入 path 库。

文件下载操作通过点击操作触发。

const cdp = await page.target().createCDPSession();
save_path = '';
await cdp.send('Page.setDownloadBehavior', {
	behavior: 'allow',
    downloadPath: path.resolve(__dirname, `${save_path}`)
    // path 的这个格式比不可少,save_path 是真正的路径。
});		// 文件下载相关行为

对于保存路径可能不存在的情况,可以通过如下代码完成路径创建。

async function dirExists(savepath) { whole = savepath.split('\\'); var now = whole[0];
    for (var i = 1; i < whole.length; ++i) {
    	now = now + '\\' + whole[i]; 
    	if (!fs.existsSync(now)) { 
            fs.mkdirSync(now); console.log(`File ${now} is not exist, now is making...`); 		  }
    }
}

文件写入操作也可以通过 fs 的 write 操作完成。


未完待续……

posted @ 2020-11-27 18:43  云烟万象但过眼  阅读(249)  评论(0编辑  收藏  举报