Sas*_*lla 2 javascript playwright
我正在使用 Playwright 来抓取一些数据。如何单击页面上与选择器匹配的所有链接?
const { firefox } = require('playwright');
(async () => {
const browser = await firefox.launch({headless: false, slowMo: 50});
const page = await browser.newPage();
await page.goto('https://www.google.com');
page.pause(); // allow user to manually search for something
const wut = await page.$$eval('a', links => {
links.forEach(async (link) => {
link.click(); // maybe works?
console.log('whoopee'); // doesn't print anything
page.goBack(); // crashes
});
return links;
});
console.log(`wut? ${wut}`); // prints 'wut? undefined'
await browser.close();
})();
Run Code Online (Sandbox Code Playgroud)
一些问题:
console.log里面$$eval没有做任何事情。page.goBack()并page.pause()在 eval 内部导致崩溃。$$eval是undefined(如果我注释掉,page.goBack()那么我就得到一个返回值)。如果我返回links.length而不是links,它是正确的(即它是一个正整数)。啊?我得到类似的结果:
const links = await page.locator('a');
await links.evaluateAll(...)
Run Code Online (Sandbox Code Playgroud)
显然我不知道自己在做什么。实现这样的目标的正确代码是什么?
(XY问题警报:我实际上并不关心我是否使用$$eval,,Playwright或者坦白地说,甚至是Javascript来做到这一点;我真正想做的就是使这项工作能够在任何语言或工具中进行)。
const { context } = await launch({ slowMo: 250 });
const page = await context.newPage();
await page.goto('/sf/ask/4949197431/');
const links = page.locator('a:visible');
const linksCount = await links.count();
for (let i = 0; i < linksCount; i++) {
await page.bringToFront();
try {
const [newPage] = await Promise.all([
context.waitForEvent('page', { timeout: 5000 }),
links.nth(i).click({ modifiers: ['Control', 'Shift'] })
]);
await newPage.waitForLoadState();
console.log('Title:', await newPage.title());
console.log('URL: ', page.url());
await newPage.close();
}
catch {
continue;
}
}
Run Code Online (Sandbox Code Playgroud)
有多种方法可以做到这一点,但我最喜欢这种方法。单击链接,等待页面加载,然后返回上一页会带来很多问题 - 最重要的是,对于许多页面来说,每次加载页面时链接都可能会发生变化。Ctrl+Shift+单击将在新选项卡中打开,您可以使用Promise.all 模式并捕获 'page' 事件来访问该选项卡。
我只在此页面上尝试过此操作,因此我确信还会出现大量其他问题。但特别是对于此页面,使用“a:visible”对于防止卡在隐藏链接上是必要的。整个点击操作都包含在 try/catch 中,因为某些链接不是真正的链接,并且不会打开新页面。
根据您的用例,最简单的方法可能是从每个链接中获取所有 href:
const links = page.locator('a:visible');
const linksCount = await links.count();
const hrefs = [];
for (let i = 0; i < linksCount; i++) {
hrefs.push(await links.nth(i).getAttribute('href'));
}
console.log(hrefs);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11910 次 |
| 最近记录: |