【发布时间】:2020-07-07 10:29:49
【问题描述】:
我有一个项目要从内部 CRM 中抓取某些客户购买的产品。这个 CRM 使用了很多动态加载的磁贴,所以没有多少一致的类名(很多在每次页面加载时随机附加一个 ID),而且在同一个类名的页面上也有很多不同的报表/元素,所以我无法在整个页面中查询元素选择器。
我已经通过 xpath 确定了我想要的“父”元素。然后我想向下钻取并仅获取与查询选择器匹配的子项的 innerText(我看到的大多数线程都有人在整个页面上执行查询选择器,这将从我不想要的菜单中获得结果)。
我可以在浏览器控制台中使用常规 Javascript 来执行此操作,但我不知道如何在 Node/Puppeteer 中执行此操作。这是我目前所拥有的:
//Getting xpath of the "box" that contains all of the product tiles that a customer has
const productsBox = await page.$x("/html/body/blah/blah/blah");
这就是它崩溃的地方。我不太熟悉某些语法或理解 Puppeteer 的文档,但我尝试了几种不同的方法(我对使用 => 格式的函数也不太满意。Puppeteer 文档有一个 example我正在尝试做的事情,但我尝试了相同的结构,但它也没有返回任何内容):
//Tried using the elementHandle.$$eval approach on the zero index of my xpath results,
//but doesn't return anything when I console.log(productsList)
const productsList = await productsBox[0].$$eval('.title-heading', function parseAndText (products) {
productsList=[];
for (i=0; i<products.length; i++) {
productsList.push(products[i].innerText.trim());
}
return productsList;
}
);
//Tried doing the page.$$eval approach with selector, passing in the zero index of my xpath
const productsList = await page.$$eval('.title-heading', function parseAndText (products) {
productsList=[];
for (i=0; i<products.length; i++) {
productsList.push(products[i].innerText.trim());
}
return productsList;
}, productsBox[0]
//Tried the page.evaluate and then page.evaluateHandle approach on the zero index of my xpath,
//doing the query selection inside the evaluation and then doing something with that.
let productsList= await page.evaluateHandle(function parseAndText(productsBoxZero) {
productsInnerList = productsBoxZero.querySelectorAll(".title-heading");
productsList=[];
for (i=0; i<productsInnerList.length; i++) {
productsList.push(productsInnerList[i].innerText.trim());
//Threw a console log here to see if it does anything,
//But nothing is logged
console.log("Pushed product " + i + " into the product list");
}
return productsList;
}, productsBox[0]);
在输出方面,我已经在控制台记录了一些变量,我得到了这个:
productsBox is JSHandle@node
productsBox[0] is JSHandle@node
productList is
为了比较,我在控制台中通过 Javascript 并行执行此操作,以确保我正确地单步执行逻辑并得到我期望的结果:
>productsBox=$x("/html/body/blah/blah/blah");
>productsInnerList=productsBox[0].querySelectorAll(".title-heading");
>productsInnerList.length;
//2, and this customer has 2 products
>productsList=[];
>for (i=0; i<productsInnerList.length; i++) {
productsList.push(productsInnerList[i].innerText.trim());
};
>console.log(productsList)
>["Product 1", "Product 2"]
感谢您阅读本文,感谢您的帮助!
[编辑]
对于一些额外的研究,我尝试使用 page.evaluateHandle 并尝试记录我的变量到目前为止:
productsBox is JSHandle@node
productsBox[0] is JSHandle@node
productList is JSHandle@array
这是进步。我试着做:
let productsText=await productsList.jsonValue();
但是当我尝试输出时,我什么也得不到:
await console.log("productsText is " + productsText);
productsBox is JSHandle@node
productsBox[0] is JSHandle@node
productList is JSHandle@array
productsText is
【问题讨论】:
标签: javascript node.js xpath puppeteer innertext