需要使用querySelector选择非常特定的元素,而不返回undefined



我正在使用Puppeter抓取一个站点的数据,并且需要从该站点获取一段真正特定的数据,我试图使用querySelector来获取数据所在的类名,但事实证明这相当困难,因为还有22个其他元素使用了确切的类名(类名为FormData(,在22个中,这是第18个,我一直试图选择它并打印出来,但没有成功,我总是收到同样的错误或类似的东西。

代码

// MODULES
const puppeteer = require("puppeteer");
// Url where we get and scrape the data from
const URL = "https://www.sec.gov/edgar/search/#/category=form-cat2";
(async () => {
try {
const chromeBrowser = await puppeteer.launch({ headless: true });
const page = await chromeBrowser.newPage();
await page.goto(URL, {timeout: 0});
const getInfo = await page.evaluate(() => {
const secTableEN = document.querySelector(".table td.entity-name");
const secTableFiled = document.querySelector(".table td.filed");
const secTableLinkPrice = document.querySelector('.FormData')[17];
return {
secTableEN: secTableEN.innerText,
secTableFiled: secTableFiled.innerText,
secTableLinkPrice: secTableLinkPrice.innerText,
};
});
console.log(
"Name: " + getInfo.secTableEN, 'n' +
"Amount Purchased: " + getInfo.secTableLinkPrice, 'n'
);
await page.close();
await chromeBrowser.close();
} catch (e) {
console.error(e)
}
})();

我一直得到的错误是:Error: Evaluation failed: TypeError: Cannot read properties of undefined (reading 'innerText'),并且只有当我尝试返回secTableLinkPrice.innerText时才会发生,另外两个总是很好。我能做什么?

显然,您想要从顶部结果中获得的价格在一个弹出窗口中,因此您需要单击其中一个.preview-file链接才能显示该弹出窗口。只有这样,您才能从iframe模态中选择.FormData

const puppeteer = require("puppeteer"); // ^19.1.0
const url = "<YOUR URL>";
let browser;
(async () => {
browser = await puppeteer.launch();
const [page] = await browser.pages();
const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36";
await page.setUserAgent(ua);
await page.goto(url, {waitUntil: "domcontentloaded"});
const $ = (...args) => page.waitForSelector(...args);
await (await $(".filetype .preview-file")).click();
const frame = await (await $("#ipreviewer")).contentFrame();
await frame.waitForSelector(".FormText");
const price = await frame.$$eval(".FormText", els =>
els.find(e => e.textContent.trim() === "$")
.parentNode
.textContent
.trim()
);
console.log(price);
})()
.catch(err => console.error(err))
.finally(() => browser?.close());

现在,弹出窗口会触发对XML文件(看起来是HTML(的网络请求,所以下载它可能最容易,因为它可能拥有您想要的所有数据。在下面的代码中,我实际上正在使用Puppeteer解析和遍历HTML,所以看起来需要做更多的工作,但根据您的需要,也许您可以将此文件保存到磁盘:

// ... same as above ...
let browser;
(async () => {
browser = await puppeteer.launch();
const [page] = await browser.pages();
const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36";
await page.setUserAgent(ua);
await page.goto(url, {waitUntil: "domcontentloaded"});
const responseP = page.waitForResponse(res =>
res.status() === 200 && res.url().endsWith(".xml")
);
const a = await page.waitForSelector(".filetype .preview-file");
await a.click();
const html = await (await responseP).text();
await page.evaluate(html => document.body.outerHTML = html, html);
const price = await page.$$eval(".FormText", els =>
els.find(e => e.textContent.trim() === "$")
.parentNode
.textContent
.trim()
);
console.log(price);
})()
.catch(err => console.error(err))
.finally(() => browser?.close());

最后,有些文档没有价格,所以上面的代码只适用于"4(内幕交易报告(";。此外,我还没有验证所有这些";类型4";报告完全相同。您可能需要在代码中处理此问题,然后小心地继续操作。

相关内容

最新更新