简体   繁体   English

剧作家在暴露功能的范围内使用Page

[英]Playwright use Page within the context of exposed function

I'm having trouble with Playwright's expose_function API.我在使用 Playwright 的expose_function API 时遇到问题。 I want to be able to also pass Page into exposed functions to be able to navigate, use locators etc. withing the context of exposed function.我还希望能够将Page传递到公开函数中,以便能够在公开函数的上下文中导航、使用定位器等。

The problem is Page instance in exposed function becomes somehow "disconnected" from it's original, and doesn't do navigations, locators etc. Any calls to Page methods appear to block indefinitely.问题是公开函数中的 Page 实例以某种方式与其原始“断开连接”,并且不执行导航、定位器等。对 Page 方法的任何调用似乎都会无限期地阻塞。

Consider this simplified example:考虑这个简化的例子:

from playwright.sync_api import sync_playwright, Page
from functools import partial


def search_title(page: Page, title: str):
    print(title)
    page.goto(f"https://bing.com?q={title}")


def main():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        context = browser.new_context(viewport={ 'width': 1920, 'height': 1024 })
        page = context.new_page()
        page.goto(f"https://wikipedia.org")
        context.expose_function("search_title", partial(handle_title, page))
        page.evaluate("window.onload = () => search_title(document.title)")
        while True:
            page.wait_for_timeout(1000)


if __name__ == "__main__":
    main()

What it does is prints the title, and halts at navigation step indefinitely.它所做的是打印标题,并在导航步骤中无限期地停止。

EDIT : using asyncio version of the same code above produces playwright._impl._api_types.Error: Execution context was destroyed, most likely because of a navigation.编辑:使用上面相同代码的 asyncio 版本会产生playwright._impl._api_types.Error: Execution context was destroyed, most likely because of a navigation. error:错误:



from playwright.async_api import  Page, async_playwright
import asyncio
from functools import partial
import time

async def handle_title(page: Page, title: str):
    print(title)
    print(page)
    await page.goto(f"https://bing.com?q={title}")


async def main():
     async with async_playwright() as p:
        browser = await p.chromium.launch(headless=False)
        context = await browser.new_context(viewport={ 'width': 1920, 'height': 1024 })
        page = await context.new_page()
        await page.goto(f"https://wikipedia.org")
        await context.expose_function("handle_title", partial(handle_title, page))
        await page.evaluate("window.onload = () => handle_title(document.title)")
        while True:
            await asyncio.sleep(1)


if __name__ == "__main__":
    asyncio.run(main())

I found that it's possible to use Page in context of exposed function, as long as:我发现可以在公开功能的上下文中使用 Page ,只要:

  1. You use async Playwright (as per @hardkoded suggestion)您使用异步剧作家(根据@hardkoded 的建议)
  2. Don't navigate away (as per @Charchit suggestion)不要离开(根据@Charchit 的建议)
from playwright.async_api import  Page, async_playwright
import asyncio
from functools import partial
import time


async def handle_title(page: Page, title: str):
    # page = page_var.get()
    print(page)
    await page.locator("#searchInput").type(f"{title}")
    return "hello world"


async def main():
     async with async_playwright() as p:
        browser = await p.chromium.launch(headless=False)
        context = await browser.new_context(viewport={ 'width': 1920, 'height': 1024 })
        page = await context.new_page()
        await page.goto(f"https://wikipedia.org")
        await context.expose_function("handle_title", partial(handle_title, page))
        await page.evaluate("window.onload = () => handle_title(document.title)")
        while True:
            await asyncio.sleep(1)



asyncio.run(main())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM