![](/img/trans.png)
[英]With Puppeteer: How can I get an iframe from its parent element selector?
[英]why can't puppeteer scrape an element from a iframe even if I add the selector
我使用 puppeteer 編寫了一個小型網絡抓取工具,但我似乎無法正確提取我想要的信息。 你能幫我找出錯誤嗎?
背景:我想抓取一個網站,該網站表明該城市允許房東為休息控制的公寓(例如黃金地段)增加多少保費。
到目前為止我所做的(下面的代碼):我能夠瀏覽網站,訪問 iframe,編寫一些輸入,單擊按鈕並獲得結果匯總表。 我想提取前兩行的日期和歐元值並將其保存到 json 中。 最終,我想對一堆地址執行此操作(仍然需要檢查我如何輕松地執行此操作),然后匯總此信息(與上一期間的溢價差異等)。
問題:我可以隔離我想要的相關信息的選擇器,但使用 frame.$$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 並閱讀了許多不同的線程,但還沒有找到解決方案。 我希望一切都清楚,我將不勝感激!
PS 我對 JS/node.js/puppeteer 很陌生,如果有一些不准確的地方,我很抱歉,我還不知道語言的來龍去脈。
一些考慮。
await frame.type('#input_adresse', 'Gumpendorfer Straße 12, 1060 Wien', { delay: 1000 });
— 1000 似乎太長了,也許 100 甚至 50 就足夠了。
比textContent
更喜歡innerText
以獲得更具可讀性的內容。
這是您如何獲得更多結構化數據、包含行和單元格的多維數組:
// 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;
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.