Puppeteerを利用する上で便利にする関数集

2024/04/11に公開

Puppeteerって凄いんだけど、ちょっと不便よね。

特に、SPAの時に。

具体的には、何かをクリックして、描写が変わった事を待ち受ける時。

システム的には、以下のように言うよね。

  • 要素をクリックして、対象の要素が表示するまで待つ。
  • 要素をクリックして、対象の要素がdisplay:noneじゃなくなるまで待つ。
  • 要素をクリックして、対象の要素が非表示になるまで待つ。
  • 要素をクリックして、対象の要素がdisplay:noneになるまで待つ。
  • 要素をクリックして、対象の要素が表示して、消えるまで待つ。

こんな事って、毎回必要になるんだけど、
毎回書いてちゃきりが無いから、公開する。

ちょっと古い書き方だけど許してください。

.env
puppet_wait_ms = 500
puppet_wait_count = 60
puppet_crm_wallet_backspace_time = 10
util.js
const util = {
	//elmの親要素を取得する
    getOuter: async(elm) => {
        return await util.getText(elm, 'outerHTML');
    },
	//elmの中のhtmlを取得する
    getInner: async(elm) => {
        return await util.getText(elm, 'innerHTML');
    },
	//elmの中のテキストコンテンツを取得する
    getContent: async(elm) => {
        return await util.getText(elm, 'textContent');
    },
	/**
	 * elmの中のpropertyを取得する
	 * @param  ElementHandle  elem puppeteerのElementHandle
	 * @param  string  property 属性名
	 */
    getText: async(elm, property) => {
        const h = await elm.getProperty(property);
        return await h.jsonValue();
    },
	/**
	 * elmに特定のClass名が指定されているか確認する
	 * @param  ElementHandle  elem puppeteerのElementHandle
	 * @param  string className 
	 */
    hasClass: async(elm, className) => {
        const classNames = await (await elm.getProperty('className')).jsonValue();
        if (classNames.indexOf(className) > -1) {
            return true;
        }
        return false;
    },
	//elmのValueを取得する
    getVal: async(elm) => {
        const value = await elm.evaluate((node) => {
            return node.value;
        });
        return value;
    },
	/**
	 * 対象の要素のelementをブラウザのConsleに表示する
	*/
    debug: async(elm) => {
        await elm.evaluate((node) => {
            console.log(node);
        });
    },

    consolelog: async(elm) => {
        const debug = async(targ) => {
            await util.debug(targ);
            const html = await util.getOuter(targ);
            console.log(html);
        }
        if (Array.isArray(elm)) {
            for (let i = 0; i < elm.length; i++) {
                await debug(elm[i]);
            }
        } else {
            await debug(elm);
        }
    },

};
module.exports = util;
wait.js
const Util = require('./util');

const wait = {
    /**
     * 指定時間処理を止める
     */
    sleep: async(time) => {
        if (time === undefined) {
            time = process.env.puppet_wait_ms;
        }
        return new Promise(resolve => {
            setTimeout(() => {
                resolve();
            }, time);
        });
    },
    forGetIndexChildSelecterEvalHund: async(elm, selecter, index) => {
        if (index === undefined) {
            index = 0;
        }
        let isShow = false;
        let targElms = {};
        for (let i = 1; i <= process.env.puppet_wait_count; i++) {
            try {
                targElms = await elm.$$(selecter);
                let isEvalHand = await targElms[index].evaluateHandle((node) => {
                    return true;
                });
                if (isEvalHand) {
                    isShow = true;
                    break;
                }
            } catch (error) {

            }
            await wait.sleep(1000);
        }
        if (isShow === false) {
            throw new Error(process.env.puppet_wait_count + '回待ったけどダメ!');
        } else {
            return targElms[index];
        }
    },
    /**
     * 指定のエレメントの中に、selecterに指定する要素が表示されるまで待つ
     * @param  ElementHandle  elem puppeteerのElementHandle
     * @param  string  selecter
     * @return Promise  listで返す
     */
    forChildSelecter: async(elm, selecter) => {
        let isShow = false;
        let targElms = {};
        for (let i = 1; i <= process.env.puppet_wait_count; i++) {
            try {
                targElms = await elm.$$(selecter);
                if (targElms.length > 0) {
                    isShow = true;
                    break;
                }
            } catch (error) {

            }
            await wait.sleep();
        }
        if (isShow === false) {
            throw new Error(process.env.puppet_wait_count + '回待ったけどダメ!');
        } else {
            return targElms;
        }
    },
    /**
     * 指定のエレメントの中のselecter要素が消えるまで待つ
     * @param  ElementHandle  elem puppeteerのElementHandle
     * @param  string  selecter
     */
    forChildSelecterHide: async(elm, selecter) => {
        let isShow = true;
        let targElms = {};
        for (let i = 1; i <= process.env.puppet_wait_count; i++) {
            targElms = await elm.$$(selecter);
            if (targElms.length == 0) {
                isShow = false;
                break;
            }
            await wait.sleep();
        }
        if (isShow === true) {
            throw new Error(process.env.puppet_wait_count + '回待ったけどダメ!');
        } else {
            return true;
        }
    },
    /**
     * 指定のエレメントの中のselecter要素が作られて、消えるまで待つ
     * @param  ElementHandle  elem puppeteerのElementHandle
     * @param  string  selecter
     */
    forChildSelecterShowAndHide: async(elm, selecter) => {
        await wait.forChildSelecter(elm, selecter);
        await wait.forChildSelecterHide(elm, selecter);
        return true;
    },
    /**
     * ElementHandleから指定のClassNameが無くなるのを待つ。
     * 再帰確認時間はenv.puppet_waitでms
     */
    removeClass: async(elem, targClassName) => {
        let isRemove = false;
        for (let i = 1; i <= process.env.puppet_wait_count; i++) {
            let handle = await elem.getProperty('className');
            let classNames = await handle.jsonValue();
            if (classNames.indexOf(targClassName) == -1) {
                isRemove = true;
                break;
            }
            await wait.sleep();
        }
        if (isRemove === false) {
            throw new Error(process.env.puppet_wait_count + '回待ったけどダメ!');
        } else {
            return true;
        }
    },
    /**
     * 横スクロールができるまで、
     */
    scrollLeft: async(elm, targScroll) => {
        let isScroll = false;
        for (let i = 1; i <= process.env.puppet_wait_count; i++) {
            let scrollLeft = await elm.evaluate((node, targScroll) => {
                node.scrollLeft = targScroll;
                return node.scrollLeft;
            }, targScroll)
            if (scrollLeft == targScroll) {
                isScroll = true;
                break;
            }
            await wait.sleep();
        }
        if (isScroll === false) {
            throw new Error('横スクロール:' + process.env.puppet_wait_count + '回待ったけどダメ!');
        } else {
            return true;
        }
    }
};
module.exports = wait;
GitHubで編集を提案

Discussion