Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9360

【Node.js、Javascript】Seleniumで要素のXPathを一気に取得する。

$
0
0
はじまり 一般的にDOMから要素のXPathを取得する方法は、ブラウザの開発者ツールからとされています。 しかし、Seleniumで要素にアクセスするためにいちいちDOMを右クリックしてXPathを取得するのも面倒だと思います。僕の場合は、300回右クリックしてXPathをメモするのは嫌だったので、一気にXPathを取得する方法を探しました。 今回は、そのときのソースを掲載します。 ソース 今回の方法では、2つファイルを作り実現しました。 作るファイルは、ブラウザで実行させるスクリプトが入ったファイルと、普通にseleniumを実行するファイルです。 Chromeで実行し、対象のCSSクラス名はcheckboxでした。 まず、ブラウザ側のファイルとなります。 最後の方は文法としては変ですが、配列のインデックスをスクリプトに載せるために"scriptSeparator"と記述しています。 ブラウザ側のファイル.js function getXpathByElement (element) { var NODE_TYPE_ELEMENT_NODE = 1; if (element instanceof Array) { element = element[0]; } if (element.nodeType != NODE_TYPE_ELEMENT_NODE) { throw new ErrorException('nodes other than the element node was passed. node_type:'+ element.nodeType +' node_name:'+ element.nodeName); } var stacker = []; var node_name = ''; var node_count = 0; var node_point = null; do { node_name = element.nodeName.toLowerCase(); if (element.parentNode.children.length > 1) { node_count = 0; node_point = null; for (i = 0;i < element.parentNode.children.length;i++) { if (element.nodeName == element.parentNode.children[i].nodeName) { node_count++; if (element == element.parentNode.children[i]) { node_point = node_count; } if (node_point != null && node_count > 1) { node_name += '['+ node_point +']'; break; } } } } stacker.unshift(node_name); } while ((element = element.parentNode) != null && element.nodeName != '#document'); return '/' + stacker.join('/').toLowerCase(); } return getXpathByElement(document.getElementsByClassName("checkbox")["scriptSeparator"]); そして、seleniumを実行するファイルです。 Selenium用ファイル.js const { Builder, By } = require('selenium-webdriver'); const fs = require("fs"); const _ = require("lodash"); const getTextLines = (fileName) => { const separator = '\n'; let text = fs.readFileSync(`./${fileName}`, 'utf8'); let lines = text.toString().split(separator); return lines; } const getXpathsByClassName = async(driver, className) => { let elements = []; let xpath = ''; let xpaths = []; const scriptFileName = 'lib/getXpathByElement.js'; let script = await getTextLines(scriptFileName).join('\t'); let scripts = await script.toString().split('\"scriptSeparator\"'); elements = await driver.findElements(By.className(className)); for (let i = 0; i < elements.length; i++){ xpath = await driver.executeScript(`${scripts[0]}${i}${scripts[1]}`); xpaths.push(_.cloneDeep(xpath)); } return new Promise( resolve => resolve(xpaths) ); }; let driver; describe("テスト", () => { before(() => { driver = new Builder().forBrowser("chrome").build(); }); after(() => { return driver.quit(); }); it{(`URLを開いたり、対象の要素を画面上に表示する。`), async () => { // URLを開いたり、対象の要素を画面上に表示する処理 }}; it(`XPath取得`, async () => { xpathArray = await getXpathsByClassName(driver, 'checkbox'); }); }); 他に試した方法 driver.findElements(By.className(className))で取得した要素をexecuteScriptに渡す。 ブラウザ側で認識している要素とどうやら違うようで、返り値がすべてnullになったので、失敗。 ブラウザ側でXPathの配列を作る。 メモリ不足エラーでブラウザが止まり、失敗。 おしまい ブラウザ側のファイルはこちらを参考にしています。とても助かりました!

Viewing all articles
Browse latest Browse all 9360

Trending Articles