Puppeteer 没有可视化完整的 SVG 图表
Puppeteer Does Not Visualise Complete SVG Chart
我在试用 Puppeteer 中使用此代码:
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.barchart.com/futures/quotes/ESM19/interactive-chart/fullscreen');
const linkHandlers = await page.$x("//li[contains(text(), '1D')]");
if (linkHandlers.length > 0) {
await linkHandlers[0].click();
} else {
throw new Error("Link not found");
}
await page.$eval('input[name="fieldInput"]', el => el.value = '1');
console.log(await page.content())
// const text = page.evaluate(() => document.querySelector('rect'))
// text.then((r) => {console.log(r[0])})
await page.screenshot({path: 'screenshot.png'});
await browser.close();
在 Chrome 浏览器中加载的同一页面显示了指示价格变动的条形图,但在 Puppeteer 中获得的屏幕截图中,图表是空的。
此外 page.content()
给出的 html 与我在 Chrome.
中检查元素时看到的完全不同
问题
输入更改时,您没有等待请求解决。由于更改会触发请求,因此您应该使用 page.waitForResponse
等待数据加载。
此外,这是一个Angular应用程序,如果您只是通过el.value = '1'
更改字段的值,它似乎不喜欢它。相反,您需要尝试表现得更像一个人(然后按退格键并键入输入值)。
解决方案
首先,您从文档中获取元素句柄 (input[name="fieldInput"
)。然后,聚焦该元素,按退格键删除其中的值。之后键入所需的输入值。
输入字段现在有了正确的值,现在我们需要通过在元素上调用 blur()
来触发 blur 事件。同时,我们等待对服务器的请求完成。请求完成后,我们应该给页面几毫秒的时间来呈现数据。
总而言之,生成的代码如下所示:
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.barchart.com/futures/quotes/ESM19/interactive-chart/fullscreen');
// wait until the element appears
const linkHandler = await page.waitForXPath("//li[contains(text(), '1D')]");
await linkHandler.click();
// get the input field, focus it, remove what's inside, then type the value
const elementHandle = await page.$('input[name="fieldInput"]');
await elementHandle.focus();
await elementHandle.press('Backspace');
await elementHandle.type('1');
// trigger the blur event and wait for the response from the server
await Promise.all([
page.waitForResponse(response => response.url().includes('https://www.barchart.com/proxies/timeseries/queryminutes.ashx')),
page.evaluate(el => el.blur(), elementHandle)
]);
// give the page a few milliseconds to render the diagram
await page.waitFor(100);
await page.screenshot({path: 'screenshot.png'});
await browser.close();
代码改进
我还删除了 page.$x
function and replaced it with the page.waitForXPath
功能。这可确保您的脚本等到页面加载完毕并且您要单击的元素在脚本继续之前可用。
我在试用 Puppeteer 中使用此代码:
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.barchart.com/futures/quotes/ESM19/interactive-chart/fullscreen');
const linkHandlers = await page.$x("//li[contains(text(), '1D')]");
if (linkHandlers.length > 0) {
await linkHandlers[0].click();
} else {
throw new Error("Link not found");
}
await page.$eval('input[name="fieldInput"]', el => el.value = '1');
console.log(await page.content())
// const text = page.evaluate(() => document.querySelector('rect'))
// text.then((r) => {console.log(r[0])})
await page.screenshot({path: 'screenshot.png'});
await browser.close();
在 Chrome 浏览器中加载的同一页面显示了指示价格变动的条形图,但在 Puppeteer 中获得的屏幕截图中,图表是空的。
此外 page.content()
给出的 html 与我在 Chrome.
问题
输入更改时,您没有等待请求解决。由于更改会触发请求,因此您应该使用 page.waitForResponse
等待数据加载。
此外,这是一个Angular应用程序,如果您只是通过el.value = '1'
更改字段的值,它似乎不喜欢它。相反,您需要尝试表现得更像一个人(然后按退格键并键入输入值)。
解决方案
首先,您从文档中获取元素句柄 (input[name="fieldInput"
)。然后,聚焦该元素,按退格键删除其中的值。之后键入所需的输入值。
输入字段现在有了正确的值,现在我们需要通过在元素上调用 blur()
来触发 blur 事件。同时,我们等待对服务器的请求完成。请求完成后,我们应该给页面几毫秒的时间来呈现数据。
总而言之,生成的代码如下所示:
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.barchart.com/futures/quotes/ESM19/interactive-chart/fullscreen');
// wait until the element appears
const linkHandler = await page.waitForXPath("//li[contains(text(), '1D')]");
await linkHandler.click();
// get the input field, focus it, remove what's inside, then type the value
const elementHandle = await page.$('input[name="fieldInput"]');
await elementHandle.focus();
await elementHandle.press('Backspace');
await elementHandle.type('1');
// trigger the blur event and wait for the response from the server
await Promise.all([
page.waitForResponse(response => response.url().includes('https://www.barchart.com/proxies/timeseries/queryminutes.ashx')),
page.evaluate(el => el.blur(), elementHandle)
]);
// give the page a few milliseconds to render the diagram
await page.waitFor(100);
await page.screenshot({path: 'screenshot.png'});
await browser.close();
代码改进
我还删除了 page.$x
function and replaced it with the page.waitForXPath
功能。这可确保您的脚本等到页面加载完毕并且您要单击的元素在脚本继续之前可用。