如何获取元素的className、Id 和nth:child(n) 以便成为一个好的稳定的querySelector?
How to get element's className, Id, and nth:child(n) in order to be a good stable querySelector?
我正在通过 X、Y 坐标获取元素。我希望我的最终字符串结果看起来像 Inspect -> copySelector:
body > div.layout.slidein-page-container > main > div.ng-scope > section.wrapper.wrapper--canvas > div > div > div > div:nth-child(2)
所以从中计算 JSHandle 将是很好的 queryString。
这是我的代码:
let chosenElement = await page.evaluate((payload) => {
return document.elementsFromPoint(payload.data.x, payload.data.y)
.map((o) => {
if (o.id) {
return o.id;
} else if (o.className) {
if (o.className.includes(' ')) {
return o.tagName.toLowerCase() + '.' + o.className.split(' ').join('.');
} else {
return o.tagName.toLowerCase() + '.' + o.className;
}
} else {
return o.tagName.toLowerCase();
}
}).reverse().join(' > ');
}, payload);
所以目前我只检查 className 和 Id,但我想让它更精确。
我首先需要帮助的是如何检查元素是否为第 nth-child(2) 示例?
你能帮我一个更好的解决方案吗
您可以将元素的 parent children 从 HTMLCollection 转换为数组:
Array.from(o.parentElement.children)
找到你的元素的索引:
const oIndex = Array.from(o.parentElement.children).indexOf(o);
return 选择器:
return `${o.tagName}:nth-child(${oIndex + 1})`;
你需要加 1 因为 nth-child 从 1 开始,数组中的索引从 0 开始;
顺便说一句:
- 您在构建选择器时忘记在 id 前添加
#
。
- 您不需要将选择器中的标记名小写
- 如果 object 有一个类名,你可以简单地 return
${o.tagName}.${Array.from(o.classList).join('.')}
我希望这对其他人有所帮助
let chosenElement = await page.evaluate((payload) => {
return document.elementsFromPoint(payload.data.x, payload.data.y)
.map((o) => {
let sibArr = Array.from(o.parentNode.children).filter(i => i.tagName === o.tagName);
if (sibArr.indexOf(o) > 0) {
let oIndex = sibArr.indexOf(o);
return `${o.tagName.toLowerCase()}:nth-child(${oIndex + 1})`;
} else if (o.id) {
return '#' + o.id;
} else if (o.className) {
return `${o.tagName.toLowerCase()}.${Array.from(o.classList).join('.')}`
} else {
return o.tagName.toLowerCase();
}
}).reverse().filter(e => !e.includes('html')).join(' > ');
}, payload);
这符合预期的结果:
body > div:nth-child(3) > header.layout__header.slidein-page > div.container > nav.nav-bar > ul.nav-bar__nav > li:nth-child(3) > a
我正在通过 X、Y 坐标获取元素。我希望我的最终字符串结果看起来像 Inspect -> copySelector:
body > div.layout.slidein-page-container > main > div.ng-scope > section.wrapper.wrapper--canvas > div > div > div > div:nth-child(2)
所以从中计算 JSHandle 将是很好的 queryString。
这是我的代码:
let chosenElement = await page.evaluate((payload) => {
return document.elementsFromPoint(payload.data.x, payload.data.y)
.map((o) => {
if (o.id) {
return o.id;
} else if (o.className) {
if (o.className.includes(' ')) {
return o.tagName.toLowerCase() + '.' + o.className.split(' ').join('.');
} else {
return o.tagName.toLowerCase() + '.' + o.className;
}
} else {
return o.tagName.toLowerCase();
}
}).reverse().join(' > ');
}, payload);
所以目前我只检查 className 和 Id,但我想让它更精确。
我首先需要帮助的是如何检查元素是否为第 nth-child(2) 示例?
你能帮我一个更好的解决方案吗
您可以将元素的 parent children 从 HTMLCollection 转换为数组:
Array.from(o.parentElement.children)
找到你的元素的索引:
const oIndex = Array.from(o.parentElement.children).indexOf(o);
return 选择器:
return `${o.tagName}:nth-child(${oIndex + 1})`;
你需要加 1 因为 nth-child 从 1 开始,数组中的索引从 0 开始;
顺便说一句:
- 您在构建选择器时忘记在 id 前添加
#
。 - 您不需要将选择器中的标记名小写
- 如果 object 有一个类名,你可以简单地 return
${o.tagName}.${Array.from(o.classList).join('.')}
我希望这对其他人有所帮助
let chosenElement = await page.evaluate((payload) => {
return document.elementsFromPoint(payload.data.x, payload.data.y)
.map((o) => {
let sibArr = Array.from(o.parentNode.children).filter(i => i.tagName === o.tagName);
if (sibArr.indexOf(o) > 0) {
let oIndex = sibArr.indexOf(o);
return `${o.tagName.toLowerCase()}:nth-child(${oIndex + 1})`;
} else if (o.id) {
return '#' + o.id;
} else if (o.className) {
return `${o.tagName.toLowerCase()}.${Array.from(o.classList).join('.')}`
} else {
return o.tagName.toLowerCase();
}
}).reverse().filter(e => !e.includes('html')).join(' > ');
}, payload);
这符合预期的结果:
body > div:nth-child(3) > header.layout__header.slidein-page > div.container > nav.nav-bar > ul.nav-bar__nav > li:nth-child(3) > a