waitForSelector突然不再在木偶师工作



我有一个正在工作的木偶演员脚本,我想将其制作成API,但我在waitForSelector方面遇到了问题。

背景:我编写了一个木偶师脚本,成功地搜索并抓取了我在代码中指定的查询结果,例如let address = xyz;。现在我想把它变成一个API,这样用户就可以查询一些东西。我设法为本地API编写了一切必要的代码(使用express(,一切都很好。我的意思是:我编码了所有服务器端的东西:我可以提出请求,scraper函数被调用,木偶师启动,执行我的搜索(我需要键入地址,从下拉列表中选择,然后按enter(。

状态:我的查询结果是iFrame中的一个表单(基本上是3列和一些行(,我想刮取所有行(稍后我将它们修改为特定的json(。它的工作方式是在表单的选择器上使用waitForSelector,然后使用frame.evaluate.

问题:当我运行正常的scraper时,一切都很好,但当我在API框架内运行(略微修改但基本相同(代码时,waitForSelector突然总是超时。我尝试了所有常见的解决方法:等待导航、截屏和检查等,但都无济于事。我已经读了很多,当我从API的上下文中调用scraper时,可能是我在异步/等待方面搞砸了什么?我对此还很陌生,所以请耐心等待。这是工作脚本的代码-我指出了的重要部分

const puppeteer = require("puppeteer");
const chalk = require("chalk");
const fs = require('fs');
const error = chalk.bold.red;
const success = chalk.keyword("green");
address = 'Gumpendorfer Straße 12, 1060 Wien';
(async () => {
try {
// open the headless browser
var browser = await puppeteer.launch();
// 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(1000)
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', address, { delay: 100});
//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')
await frame.waitForSelector('#summary > div > div > br ~ div');//This keeps failing in the API
const res = 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;
});
await browser.close();
console.log(success("Browser Closed"));
const mapFields = (arr1, arr2) => {
const mappedArray = arr2.map((el) => {
const mappedArrayEl = {};
el.forEach((value, i) => {
if (arr1.length < (i+1)) return;
mappedArrayEl[arr1[i]] = value;
});
return mappedArrayEl;
});
return mappedArray;
}
const Arr1 = res[0];
const Arr2 = res.slice(1,3);
let dataObj = {};
dataObj[address] = [];
// dataObj['lagezuschlag'] = mapFields(Arr1, Arr2);
// dataObj['adresse'] = address;
dataObj[address] = mapFields(Arr1, Arr2);
console.log(dataObj);

} catch (err) {
// Catch and display errors
console.log(error(err));
await browser.close();
console.log(error("Browser Closed"));
}

})();

我只是不明白为什么它在这种情况下有效,而在另一种情况下无效,尽管我几乎没有改变什么。对于API,我基本上将异步函数的名称更改为const search = async (address) => {,这样我就可以使用服务器端脚本中的查询来调用它。提前谢谢-我不附加API代码,因为我不想混淆这个问题。如果有必要,我可以更新

我自己解决了这个问题。事实证明,这个问题并没有我想象的那么复杂,而且解决起来非常简单。问题不在于超时的选择器,而在于以前的选择器,特别是键入和从下拉选择器中进行选择。从本质上讲,事情进展得太快了。在输入搜索查询之前,下拉列表已经被按下,胡说八道就出来了。我是如何解决的:在选择下拉菜单之前,我包括了一个waitFor(1000(电话,一切都很顺利。一个有趣的认识是,尽管有一个选择器超时,但它实际上并不是问题的根源。但正如我所说,简单得令人恼火,我问这个问题感到很愚蠢:(但也许有人会看到这一点,并从我的错误中吸取教训

最新更新