无法使用 puppeteer 获取特定的元素列表
unable to get a specific list of elements using puppeteer
我以前从未使用过这个库,所以如果这听起来像是一个愚蠢的问题,我深表歉意
所以,我想从这个网站提取一些特定的文本
https://www.unieuro.it/online/
我已经 browser.js,并且满足了使人偶操作工作的所有要求
所以我只是导航到那个网站并让它搜索一些东西
请记住这只是一个代码示例
await page.goto("https://www.unieuro.it");
await page.waitForSelector('input[name=algolia-search]');
await page.type("input[name=algolia-search]","echo dot")
await page.click(".icon-search")
到目前为止没有什么奇怪的,它按预期工作,但是在这一步之后,事情很快就会变得奇怪。
首先,我完全无法让它等待任何选择器。
我试着让它等class collapsed hits__hit
,对于元素文章,甚至版块,每次都会超时,所以我就放弃了,使用了
await page.waitForTimeout(3000);
从这里我试图提取具有 class 的元素:product-tile
具体来说,我需要标题,它位于 a
元素内,如 textContent
a
元素在 div
和 class product-tile__title
中,所以我尝试的是一个简单的 eval
var name = await page.$$eval(".product-tile__title" el => {
el.map(el => el.querySelector("a").textContent))
return el
})
这根本不起作用,它给了我一个数组中的一堆空 objects
所以我尝试安装一个名为 puppeteer recorder 的扩展,我尝试使用它生成的代码
const element1 = await page.$('.collapsed:nth-child(1) > .product-tile > .item-container > .info > .title')
在这种情况下 element1
确实包含一些内容,但它与标题没有任何关系
现在我被卡住了,我完全无法获得我需要的 object 并且互联网上的结果没有帮助。
作为旁注:
我希望有一种更简单的方法在 node 中制作爬虫,为什么所有的库都必须如此复杂并且永远不会像你希望的那样工作
这个页面对我来说有超长的加载时间,可能是因为我在地球的另一边,远离意大利,还有一些 st运行ge 行为。当我 运行 使用 Puppeteer 进行搜索时,页面 returns 17000 个结果似乎完全未经过滤。我没有费心去弄清楚为什么,因为我可以使用 https://www.unieuro.it/online/?q=echo%20dot:
直接进入搜索结果页面
const puppeteer = require("puppeteer");
let browser;
(async () => {
browser = await puppeteer.launch({headless: true});
const [page] = await browser.pages();
await page.setDefaultTimeout(10 ** 5);
await page.setRequestInterception(true);
page.on("request", req => {
req.resourceType() === "image" ? req.abort() : req.continue();
});
await page.goto("https://www.unieuro.it/online/?q=echo%20dot");
await page.waitForSelector(".product-tile__title");
const titles = await page.$$eval(
".product-tile__title ",
els => els.map(e => e.textContent)
);
console.log(titles.map(e => e.trim()));
})()
.catch(err => console.error(err))
.finally(() => browser?.close())
;
输出:
[
'Amazon Echo Dot',
'Amazon Echo Dot (4th gen)',
'Amazon Echo Dot (4th Gen)',
'Amazon Echo Dot (4th gen)',
'Amazon Echo Dot (4th gen)',
'Amazon Echo Dot (4th gen)'
]
我没有对此进行广泛测试(例如,在包含大量结果的页面上),应该有很多机会通过分析和阻止不相关的请求来缩短加载时间。
一个可能更好的方法是 hit the API directly 并完全跳过 Puppeteer:
const url = "https://mnbcenyfii-dsn.algolia.net/1/indexes/*/queries?x-algolia-agent=Algolia for JavaScript (3.35.1); Browser; JS Helper (2.28.0)&x-algolia-application-id=MNBCENYFII&x-algolia-api-key=977ed8d06b718d4929ca789c78c4107a";
const body = `{"requests":[{"indexName":"sgmproducts_prod","params":"query=echo%20dot&hitsPerPage=20&maxValuesPerFacet=20&page=0"}]}`;
fetch(url, {method: "post", body})
.then(response => {
if (!response.ok) {
throw Error(response.status);
}
return response.json();
})
.then(data => data.results[0].hits.map(e => e.title_it))
.then(results => console.log(results))
.catch(err => console.error(err))
;
您可以使用 node-fetch or axios 轻松地将其移植到 Node。
我以前从未使用过这个库,所以如果这听起来像是一个愚蠢的问题,我深表歉意
所以,我想从这个网站提取一些特定的文本
https://www.unieuro.it/online/
我已经 browser.js,并且满足了使人偶操作工作的所有要求
所以我只是导航到那个网站并让它搜索一些东西
请记住这只是一个代码示例
await page.goto("https://www.unieuro.it");
await page.waitForSelector('input[name=algolia-search]');
await page.type("input[name=algolia-search]","echo dot")
await page.click(".icon-search")
到目前为止没有什么奇怪的,它按预期工作,但是在这一步之后,事情很快就会变得奇怪。
首先,我完全无法让它等待任何选择器。
我试着让它等class collapsed hits__hit
,对于元素文章,甚至版块,每次都会超时,所以我就放弃了,使用了
await page.waitForTimeout(3000);
从这里我试图提取具有 class 的元素:product-tile
具体来说,我需要标题,它位于 a
元素内,如 textContent
a
元素在 div
和 class product-tile__title
中,所以我尝试的是一个简单的 eval
var name = await page.$$eval(".product-tile__title" el => {
el.map(el => el.querySelector("a").textContent))
return el
})
这根本不起作用,它给了我一个数组中的一堆空 objects
所以我尝试安装一个名为 puppeteer recorder 的扩展,我尝试使用它生成的代码
const element1 = await page.$('.collapsed:nth-child(1) > .product-tile > .item-container > .info > .title')
在这种情况下 element1
确实包含一些内容,但它与标题没有任何关系
现在我被卡住了,我完全无法获得我需要的 object 并且互联网上的结果没有帮助。
作为旁注:
我希望有一种更简单的方法在 node 中制作爬虫,为什么所有的库都必须如此复杂并且永远不会像你希望的那样工作
这个页面对我来说有超长的加载时间,可能是因为我在地球的另一边,远离意大利,还有一些 st运行ge 行为。当我 运行 使用 Puppeteer 进行搜索时,页面 returns 17000 个结果似乎完全未经过滤。我没有费心去弄清楚为什么,因为我可以使用 https://www.unieuro.it/online/?q=echo%20dot:
直接进入搜索结果页面const puppeteer = require("puppeteer");
let browser;
(async () => {
browser = await puppeteer.launch({headless: true});
const [page] = await browser.pages();
await page.setDefaultTimeout(10 ** 5);
await page.setRequestInterception(true);
page.on("request", req => {
req.resourceType() === "image" ? req.abort() : req.continue();
});
await page.goto("https://www.unieuro.it/online/?q=echo%20dot");
await page.waitForSelector(".product-tile__title");
const titles = await page.$$eval(
".product-tile__title ",
els => els.map(e => e.textContent)
);
console.log(titles.map(e => e.trim()));
})()
.catch(err => console.error(err))
.finally(() => browser?.close())
;
输出:
[
'Amazon Echo Dot',
'Amazon Echo Dot (4th gen)',
'Amazon Echo Dot (4th Gen)',
'Amazon Echo Dot (4th gen)',
'Amazon Echo Dot (4th gen)',
'Amazon Echo Dot (4th gen)'
]
我没有对此进行广泛测试(例如,在包含大量结果的页面上),应该有很多机会通过分析和阻止不相关的请求来缩短加载时间。
一个可能更好的方法是 hit the API directly 并完全跳过 Puppeteer:
const url = "https://mnbcenyfii-dsn.algolia.net/1/indexes/*/queries?x-algolia-agent=Algolia for JavaScript (3.35.1); Browser; JS Helper (2.28.0)&x-algolia-application-id=MNBCENYFII&x-algolia-api-key=977ed8d06b718d4929ca789c78c4107a";
const body = `{"requests":[{"indexName":"sgmproducts_prod","params":"query=echo%20dot&hitsPerPage=20&maxValuesPerFacet=20&page=0"}]}`;
fetch(url, {method: "post", body})
.then(response => {
if (!response.ok) {
throw Error(response.status);
}
return response.json();
})
.then(data => data.results[0].hits.map(e => e.title_it))
.then(results => console.log(results))
.catch(err => console.error(err))
;
您可以使用 node-fetch or axios 轻松地将其移植到 Node。