英文:
What would i use to switch to a frame in Playwright
问题
在Selenium中有一个名为switchTo
的方法,可以用于切换到一个框架。
在Playwright中有类似的东西吗?
英文:
In selenium there is a method switchTo
that can be used to switch to a frame.
Is there anything similar in Playwright?
答案1
得分: 3
是的。 语法与Selenium有些不同,但思想基本相同。 您可以使用frameLocator来深入到框架并与其中包含的元素进行交互。 可以将其视为switchTo()
。
例如,您有一个内部包含登录表单的<iframe>
,并希望填充它:
const email = 'foo@bar.com'
await page.frameLocator('#sillyWidget iframe').locator('#username').click();
for (let i = 0; i < email.length; i += 1) {
await page.keyboard.press(email[i], { delay: 20 + Math.random() * 5 });
}
列出页面上的所有框架:
const frames = await page.childFrames();
for (const frame of frames) {
console.debug('Frame --> ' + frame.url())
}
监听新框架:
page.on('frameattached', frames => frames.forEach(frame => console.debug('Frame attached' + frame.url())));
编辑:
Page
已经包括主Frame
和所有子框架,因此在这方面,switchTo()
的类比有些不合适。 框架已经存在于Page
内,因此切换到它没有意义。
如果您希望在子框架中执行许多操作,只需获取对它的引用,并像对待Page
一样使用它(几乎所有相同的功能都可用)。
还要注意:
- Playwright使用ChromeDevTools协议与浏览器通信。
- Selenium使用JSONW协议。
它们在根本上是不同的工具,尽管有些语法相同。 CDP的功能更强大,而且它是通过基于Chromium的浏览器原生支持的。
const frame = page.frame('frame-login'); // 对框架的引用
await frame.fill('#username-input', 'Phillip Masse'); // 填充框架内的输入
// [1]
await Promise.all([page.click('#btn'), page.waitForNavigation()]; // 现在在页面级别执行操作
英文:
Yes. The syntax is a bit different than Selenium but the idea is more or less the same. You can use frameLocator to drill down to the frame and interact with elements contained within. Think of it like switchTo()
.
For example, you have a <iframe>
with a login form inside, and want to fill it:
const email = 'foo@bar.com'
await page.frameLocator('#sillyWidget iframe').locator('#username').click();
for (let i = 0; i < email.length; i += 1) {
await page.keyboard.press(email[i], { delay: 20 + Math.random() * 5 });
}
List all the frames on the page:
const frames = await page.childFrames();
for (const frame of frames) {
console.debug('Frame --> ' + frame.url())
}
Listen for new frames:
page.on('frameattached', frames => frames.forEach(frame => console.debug('Frame attached' + frame.url())));
Edit:
A Page
already comprises the main Frame
and all subframes, so the switchTo()
analogy kind of breaks down in that regard. The frame already exists
inside the Page
, so switching to it doesn't make sense.
In the case you want to perform many operations in a child frame, just grab a reference to it, and work with it like you would a Page
(nearly all the same functions are available).
Also note that:
- Playwright uses ChromeDevTools protocol to speak to the browser.
- Selenium uses JSONW.
They are fundamentally different beasts, though some syntax is the same. CDP is orders of magnitude more powerful, and directly supported by chromium-based browsers by design.
const frame = page.frame('frame-login'); // reference to your frame
await frame.fill('#username-input', 'Phillip Masse'); // fill an input inside the frame
// [1]
await Promise.all([page.click('#btn'), page.waitForNavigation()]; // now do stuff on the page level
1: If memory serves, in selenium to accomplish this we'd need to driver.switch_to_default_content()
here.
答案2
得分: 1
Selenium driver
与 Playwright page
的上下文
总结 - 控制浏览器及其中所有内容 vs 与浏览器及其中特定标签(或“页面”)进行交互
并非完全如此。Playwright 采取了稍有不同的方法。与其只有一个包含驱动浏览器及其中所有内容的 driver
不同,Playwright 将其分成更具体的部分 - browser
、context
和 page
。
Browser 是整个浏览器本身,其中可以包含许多上下文和标签。
BrowserContext 用于特定的独立浏览会话(例如,由另一个标签打开的标签将属于同一会话或上下文)。
Page 用于控制浏览器/上下文内的特定标签(或“页面”)。每个单独的标签将有其自己的 Page 实例来代表它。
这样做的好处包括可以在页面之间共享上下文,更轻松地同时使用多个标签,以及在其他分离有用的区域。您不仅仅局限于只使用一个驱动程序实例来处理所有事务。
具体回答
对于您的问题,还有一个额外的部分,Frames,您可以仍然可以直接从一个 Page 中访问它,同时也允许您单独地与它交互,或者以一种方式将其视为独立的实体或“页面”。主页面实际上只是具有页面内容的自己的顶级框架,每个 iframe 基本上就是具有自己内容的自己的页面。
这里最接近 switchTo 的东西将是只需使用 .frame()
来获取特定的 Frame 并与之交互,无论是每次调用 .frame()
还是只是存储、使用和传递框架本身。它拥有您通常会使用/需要的 Page 的大多数主要方法,因此在许多情况下可以直接用于其位置。因此,虽然与 switchTo 不完全相同,它不会让页面与另一个框架(或标签)进行交互并需要切换回来,因为那实际上是在告诉驱动程序驱动其中一个,而不是另一个,您可以直接访问 Frame 本身以进行交互,保持页面代表完整的页面。
请注意,FrameLocator 和 Frame 之间存在区别。前者仅提供在 iframe 内定位元素的方法,而后者类似于另一个特定于该框架的 Page,允许您以类似的方式与之交互。
英文:
Context of Selenium driver
vs Playwright page
Tl:dr - Driving the browser and everything inside it vs interacting with the browser and specific tabs (or “pages”) within it
Not exactly. Playwright takes a slightly different approach. Instead of just a driver
which contains all the methods to drive the browser and anything within it, Playwright splits this into more specific pieces - browser
, context
, and page
.
Browser is for the browser itself as a whole, which can contain many contexts and tabs.
BrowserContext for specific independent browsing sessions (for instance, a tab opened by another tab will be part of the same session or context).
Page for controlling a specific tab (or “page”) within the browser/context. Each separate tab will have its own Page instance to represent it.
The benefits of this include being able to share context between pages, working with multiple tabs simultaneously more easily, and other areas where the separation is useful. You’re not tied down to just using one driver instance for everything.
Specific Answer
For your question there’s an added piece, Frames, which you can access directly from a Page still, while also allowing you to interact with it separately/as its own entity or “page” in a way. The main page is really just its own top frame with page content, and each iframe is basically its own page with its own content.
The closest thing to switchTo here would be to just use .frame()
to get the specific Frame and interact with it, whether by calling .frame each time or just storing, using, and passing around the frame itself. It has most of the main methods of Page you would use/need anyway, so in many cases can just be used in its place. So while not exactly like switchTo in making the page interact with the other frame (or tab) and having to switch back, because that was actually telling the driver to drive one vs the other, you can just access the Frame itself to interact with for those parts, and keep the page representing the full page.
Note that there is a difference between FrameLocator and Frame. The first solely provides a way to locate elements within an iframe, whereas the second is like another Page specific to that frame allowing you to interact with it similarly.
答案3
得分: 1
我想以简单的方式澄清提供的答案。在DOM下的iframe
情况下:
...
page.goto(URL)
# 与iframe互动
frame = page.frame_locator(iframe_selector_here) # 例如: "[title=canvas]"
frame.get_by_text("Submit").click()
# 切回主框架
page.locator("[data-test=whatever]").click()
...
英文:
I want to clarify provided answers in a simple way. In case of iframe
under the DOM:
...
page.goto(URL)
# work with iframe
frame = page.frame_locator(iframe_selector_here) # e.g: "[title=canvas]"
frame.get_by_text("Submit").click()
# switch back to main frame
page.locator("[data-test=whatever]").click()
...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论