为什么即使我添加了选择器,木偶师也无法从iframe中抓取元素



我已经使用puppeteer编写了一个小型web scraper,但似乎无法正确提取我想要的信息。你能帮我找出错误吗?

背景:我想浏览一个网站,显示该市允许房东在休息控制的公寓中增加多少溢价(例如,在黄金地段(。

到目前为止我所做的工作(代码如下(:我可以浏览网站,访问iframe,写一些输入,点击一个按钮,得到一个汇总表。我想提取前两行的日期和欧元值,并将其保存到json中。最终,我想为一堆地址做这件事(仍然需要检查我如何轻松地做到这一点(,然后汇总这些信息(与前一时期的保费差异等(。

问题:我可以隔离我想要的相关信息的选择器,但使用框架$$eval或frame。$什么也不传递(但运行时没有错误(。所以我使用了waitForSelector,它超时了,frame.evaluate抛出了一个错误。这一切都很奇怪。我的下一个方法是刮取整个表格/摘要——这很有效!当我将对象打印到控制台时,我有一个长字符串,其中包含页面上的所有内容,包括我的信息。然而,这是高度非结构化的,我不知道如何使用它来隔离我的信息。此外,我无法将其保存到json文件中(只保存了一部分文本(。

const puppeteer = require("puppeteer");
const chalk = require("chalk");
const fs = require('fs');
const error = chalk.bold.red;
const success = chalk.keyword("green");
(async () => {
try {
// open the headless browser
var browser = await puppeteer.launch({slowMo: 250});
// open a new page
var page = await browser.newPage();
// enter url in page
await page.goto(`https://mein.wien.gv.at/Meine-Amtswege/richtwert?subpage=/lagezuschlag/`, {waitUntil: 'networkidle2'});
// continue without newsletter
await page.click('#dss-modal-firstvisit-form > button.btn.btn-block.btn-light');
// let everyhting load
await page.waitFor(5000)
console.log('waiting for iframe with form to be ready.');
//wait until selector is available
await page.waitForSelector('iframe');
console.log('iframe is ready. Loading iframe content');
//choose the relevant iframe
const elementHandle = await page.$(
'iframe[src="/richtwertfrontend/lagezuschlag/"]',
);
//go into frame in order to input info
const frame = await elementHandle.contentFrame();
//enter address
console.log('filling form in iframe');
await frame.type('#input_adresse', 'Gumpendorfer Straße 12, 1060 Wien', { delay: 1000 });
//choose first option from dropdown
console.log('Choosing from dropdown');
await frame.click('#react-autowhatever-1--item-0');
console.log('pressing button');
//press button to search
await frame.click('#next-button');
// scraping data
console.log('scraping')
const optionsResult = await frame.$$eval('#summary', (options) => {
const result = options.map(option => option.textContent);
return result;
});
console.log(optionsResult);
await browser.close();
fs.writeFile("data.json", JSON.stringify(optionsResult), 'utf8', function(err) {
if(err) {
return console.log(error(err));
}
console.log(success("The data has been scraped and saved successfully! View it at './data.json'"));
});
console.log(success("Browser Closed"));
} catch (err) {
// Catch and display errors
console.log(error(err));
await browser.close();
console.log(error("Browser Closed"));
}

})();

我发布了完整的代码以供完成,重要的一点是"刮擦";从45号线开始的路段。

我仔细阅读了SO,阅读了许多不同的线程,但还没有找到解决方案。我希望一切都清楚,我将感谢任何帮助!

附言:我对JS/node.JS/poputeer还很陌生,所以如果有一些不准确的地方,我很抱歉,我还不知道这种语言的来龙去脉。

一些注意事项。

  1. await frame.type('#input_adresse', 'Gumpendorfer Straße 12, 1060 Wien', { delay: 1000 });-1000似乎太长了,也许100甚至50就足够了。

  2. 首选innerText而不是textContent以获得更可读的内容。

  3. 这就是如何获得更结构化的数据,具有行和单元格的多维数组:

// scraping data
console.log('scraping')
await frame.waitForSelector('#summary > div > div > br ~ div');
const optionsResult = await frame.evaluate(() => {
const rows = [...document.querySelectorAll('#summary > div > div > br ~ div')];
const cells = rows.map(
row => [...row.querySelectorAll('div')]
.map(cell => cell.innerText)
);
return cells;
});

最新更新