Playwright中page.locator快速查找网页元素和对象交互操作

Playwright 是一个用于自动化测试和网页操作的 Python 库,它提供了对浏览器的控制和操作的功能,包括 Chromium、Firefox 和 WebKit。使用 Playwright,您可以编写自动化测试、网页截图、网页数据提取以及网页交互等任务。
Playwright 具有以下特点:
跨浏览器支持: 支持多种主流浏览器,包括 Chromium、Firefox 和 WebKit。
强大的 API: 提供了丰富的 API,允许您模拟用户操作、获取和修改网页内容、执行 JavaScript 等。
异步支持: 支持异步操作,可以更高效地管理并发任务。
自动等待和重试: 具有内置的自动等待和重试机制,使测试更稳定可靠。
Headless 和非 Headless 模式: 可以选择在 Headless 模式(无界面)或非 Headless 模式(有界面)下运行浏览器。
交互式调试: 提供交互式调试工具,方便定位和解决问题。
社区活跃: 由微软开发并开源,拥有活跃的社区支持和更新。
Python 的 Playwright 库提供了易于使用的 API,使得在 Python 中进行网页自动化变得简单而高效。您可以使用 Playwright 来执行各种任务,包括自动化测试、网页截图、网页爬取和数据提取等。

Playwright 中的`page.locator()`方法用于在网页上查找和交互操作。它返回一个 Locator 对象 ,该对象表示匹配指定选择器及任何额外约束(例如 has_text、has_not_text、has 和 has_not)的元素集合。
可以使用 Locator 对象在匹配元素上执行操作 ,例如点击按钮或填充表单字段。Locator 对象在执行操作之前立即解析为实际的 DOM 元素,因此如果在操作之间更改了 DOM 结构,则操作将在正确的元素上执行。

与其他用于查找元素的方法(如 query_selector_all)相比,locator 提供了更多高级功能,例如等待元素出现并检查它们是否可见。这可以使测试更加稳健和可维护。

此外,locator 允许您通过指定额外约束(例如 has_text 或 has)来缩小元素查找的范围。这在查找可能没有唯一选择器的特定元素时很有用。

总的来说,Playwright 中的 locator 方法是一个强大的工具,它允许开发人员轻松查找和与网页上的元素交互。使用 Playwright 时,建议使用 locator 查找元素。

下面是 `page.locator()` 方法的详细介绍:
page.locator(selector)
page.locator(selector, **kwargs)

语法

def locator(

self,

selector: str,

*,

has_text: typing.Optional[typing.Union[str, typing.Pattern[str]]] = None,

has_not_text: typing.Optional[typing.Union[str, typing.Pattern[str]]] = None,

has: typing.Optional["Locator"] = None,

has_not: typing.Optional["Locator"] = None

) -> "Locator":
"""Page.locator

### 参数

方法的第一个参数是selector,它是一个字符串,用于解析DOM元素。

该方法还接受可选的参数has_text、has_not_text、has和has_not。
has_text 参数用于匹配包含指定文本的元素,该文本可能出现在元素的子元素或后代元素中。当传递一个字符串时,匹配是不区分大小写的,并搜索子字符串。例如,"Playwright"将匹配<article><div>Playwright</div></article>。
has_not_text 参数用于匹配不包含指定文本的元素,该文本可能出现在元素的子元素或后代元素中。当传递一个字符串时,匹配是不区分大小写的,并搜索子字符串。

has参数用于限制方法的结果,仅包含与此相对定位器匹配的元素。例如,article,它有text=Playwright匹配<article><div>Playwright</div></article>。
has_not 参数用于匹配不包含与内部定位器匹配的元素的元素。内部定位器查询与外部定位器匹配,而不是文档根。例如,您可以在<article><content><div>Playwright</div></content></article>中查找具有div的content。但是,查找具有article div的content将失败,因为内部定位器必须相对于外部定位器,不应使用外部定位器之外的任何元素。

请注意,外部和内部定位器必须属于同一框架。内部定位器不得包含FrameLocators。

### 返回值: 一个 Locator对象( 元素定位器***),可以用于查找与给定选择器匹配的元素。***

python 复制代码
    def locator(
        self,
        selector: str,
        *,
        has_text: typing.Optional[typing.Union[str, typing.Pattern[str]]] = None,
        has_not_text: typing.Optional[typing.Union[str, typing.Pattern[str]]] = None,
        has: typing.Optional["Locator"] = None,
        has_not: typing.Optional["Locator"] = None
    ) -> "Locator":
        """Page.locator

        The method returns an element locator that can be used to perform actions on this page / frame. Locator is resolved
        to the element immediately before performing an action, so a series of actions on the same locator can in fact be
        performed on different DOM elements. That would happen if the DOM structure between those actions has changed.

        [Learn more about locators](https://playwright.dev/python/docs/locators).

        Parameters
        ----------
        selector : str
            A selector to use when resolving DOM element.
        has_text : Union[Pattern[str], str, None]
            Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When
            passed a [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
            `<article><div>Playwright</div></article>`.
        has_not_text : Union[Pattern[str], str, None]
            Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element.
            When passed a [string], matching is case-insensitive and searches for a substring.
        has : Union[Locator, None]
            Narrows down the results of the method to those which contain elements matching this relative locator. For example,
            `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.

            Inner locator **must be relative** to the outer locator and is queried starting with the outer locator match, not
            the document root. For example, you can find `content` that has `div` in
            `<article><content><div>Playwright</div></content></article>`. However, looking for `content` that has `article
            div` will fail, because the inner locator must be relative and should not use any elements outside the `content`.

            Note that outer and inner locators must belong to the same frame. Inner locator must not contain `FrameLocator`s.
        has_not : Union[Locator, None]
            Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
            outer one. For example, `article` that does not have `div` matches `<article><span>Playwright</span></article>`.

            Note that outer and inner locators must belong to the same frame. Inner locator must not contain `FrameLocator`s.

        Returns
        -------
        Locator
        """

        return mapping.from_impl(
            self._impl_obj.locator(
                selector=selector,
                hasText=has_text,
                hasNotText=has_not_text,
                has=has._impl_obj if has else None,
                hasNot=has_not._impl_obj if has_not else None,
            )
        )

用法

可以使用 `locator` 对象(`page.locator()返回值)的以下方法来查找元素:

Locator是Playwright中自动等待和重试的核心部分。简而言之,Locator代表在任何时刻在页面上查找元素的方法。
可以使用page.locator()方法创建一个Locator对象实例。

**方法:**

  • **all**: 查找所有匹配的元素。
    * `first()`: 返回第一个匹配的元素。等价于 `nth(0)`。
    * `last()`: 返回最后一个匹配的元素。

  • **all_inner_texts**: 获取所有匹配元素的内部文本。

  • **all_text_contents**: 获取所有匹配元素的文本内容。

  • **and_**: 逻辑与操作符,可以与其他Locator组合使用。

  • **blur**: 触发元素失焦事件。

  • **bounding_box**: 获取元素的边界框。

  • **check**: 选中复选框或单选框。

  • **clear**: 清空输入框中的文本。

  • **click**: 单击元素。

  • **count**: 计算匹配的元素数量。

  • **dblclick**: 双击元素。

  • **dispatch_event**: 分发指定事件到元素。

  • **drag_to**: 将元素拖动到指定位置。

  • **evaluate**: 在元素上下文中执行JavaScript代码。

  • **evaluate_all**: 在所有匹配元素的上下文中执行JavaScript代码。

  • **evaluate_handle**: 获取元素的JavaScript句柄。

  • **fill**: 在输入框中输入文本。

  • **filter**: 根据指定条件过滤匹配的元素。

  • **focus**: 将焦点设置到元素。

  • **frame_locator**: 在特定的iframe中查找元素。

  • **get_attribute**: 获取元素的属性值。

  • **get_by_alt_text**: 根据alt属性的值查找元素。

  • **get_by_label**: 根据标签查找元素。

  • **get_by_placeholder**: 根据placeholder属性的值查找元素。

  • **get_by_role**: 根据角色查找元素。

  • **get_by_test_id**: 根据测试ID查找元素。

  • **get_by_text**: 根据文本内容查找元素。

  • **get_by_title**: 根据标题查找元素。

  • **highlight**: 在页面上突出显示匹配的元素。

  • **hover**: 将鼠标悬停在元素上。

  • **inner_html**: 获取元素的内部HTML。

  • **inner_text**: 获取元素的内部文本。

  • **input_value**: 获取输入框中的值。

  • **is_checked**: 检查元素是否被选中。

  • **is_disabled**: 检查元素是否被禁用。

  • **is_editable**: 检查元素是否可编辑。

  • **is_enabled**: 检查元素是否可用。

  • **is_hidden**: 检查元素是否隐藏。

  • **is_visible**: 检查元素是否可见。

  • **locator**: 创建新的Locator实例。

  • **nth**: 获取匹配元素中的第N个。

  • **or_**: 逻辑或操作符,可以与其他Locator组合使用。

  • **press**: 模拟按键操作。

  • **press_sequentially**: 依次按下多个按键。

  • **screenshot**: 对元素进行截图。

  • **scroll_into_view_if_needed**: 将元素滚动到视图中。

  • **select_option**: 选择下拉列表中的选项。

  • **select_text**: 选择文本内容。

  • **set_checked**: 设置复选框或单选框的选中状态。

  • **set_input_files**: 设置输入文件的值。

  • **tap**: 轻触元素。

  • **text_content**: 获取元素的文本内容。

  • **uncheck**: 取消选中复选框或单选框。

  • **wait_for**: 等待匹配的元素出现。

示例

下面是一个使用 `page.locator()` 方法查找元素的示例:


要输出所有匹配元素的HTML内容,包括元素本身,循环遍历元素列表,并分别获取每个元素的HTML内容。

以下是示例代码:

elements = await page.locator('input').all()

for element in elements:

html_content = await element.evaluate('(element) => element.outerHTML ')

print(html_content)

这将打印所有匹配的输入框元素的HTML内容,包括元素本身。

JavaScript箭头函数表达式的语法比普通函数表达式更简洁。


evaluate: 在元素上下文中执行JavaScript代码。

evaluate_all: 在所有匹配元素的上下文中执行JavaScript代码。

evaluate_handle: 获取元素的JavaScript句柄。

python 复制代码
import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as playwright:
        browser = await playwright.chromium.launch(headless=False)
        page = await browser.new_page()

        await page.set_content('''
            <div id="my_div" class="container">
                <H4>type、press 和 check 方法来模拟用户与页面元素的交互操作</H4>
                <p>Paragraph 1</p>
                <p>Paragraph 2</p>
                <p>Paragraph 3</p>
                <label for="my_input">my_input :<input type="text" id="my_input"></label><BR><BR>
                <button id="my_button">Click Me</button>
                <input type="checkbox" id="my_checkbox">
            </div>
        ''')

        # 创建一个Locator对象来查找按钮元素
        button_locator = page.locator('#my_button')

        # 使用evaluate方法在按钮元素上下文中执行JavaScript代码
        button_text = await button_locator.evaluate('(element) => element.textContent')
        print('Button Text:', button_text)

        # 使用evaluate_all方法在按钮元素上下文中执行JavaScript代码
        all_elements = await button_locator.evaluate_all('() => Array.from(document.querySelectorAll("p")).map(p => p.outerHTML)')
        print('All Elements:', all_elements)

        # 使用evaluate_handle方法获取按钮元素的JavaScript句柄
        button_handle = await button_locator.evaluate_handle('(element) => element.outerHTML')
        print('Button Handle:', button_handle)

        await browser.close()

asyncio.run(main())

这段代码中,我们使用了 map 函数和 Array.from 来获取所有段落元素的**outerHTML 属性**。同时,直接获取按钮元素的 outerHTML 属性,以便输出按钮的 HTML 元素。

python 复制代码
# 导入 Playwright
from playwright.async_api import async_playwright
import asyncio
from playwright.async_api import ElementHandle

# 异步函数来运行 Playwright
async def main():
    # 创建 Playwright 实例
    async with async_playwright() as playwright:
        # 启动 Chromium 浏览器
        browser = await playwright.chromium.launch(headless=False)
        # 创建新页面
        page = await browser.new_page()
        # 设置页面内容
        await page.set_content('''
            <div id="my_div" class="container">
                <H4>type、press 和 check 方法来模拟用户与页面元素的交互操作</H4>
                <p>Paragraph 1</p>
                <p>Paragraph 2</p>
                <p>Paragraph 3</p>
                <label for="my_input">my_input :<input type="text" id="my_input"></label><BR><BR>
                <button id="my_button">Click Me</button>
                <input type="checkbox" id="my_checkbox">
            </div>
        ''')

        print('****************模拟用户操作*********************')

                # 等待3秒
        await page.wait_for_timeout(3000)


        # 在输入框中输入文本
        await page.type('#my_input', 'Hello, Playwright!')
        # 在按钮上执行点击操作
        await page.press('#my_button', 'Enter')

        # 在复选框上执行勾选操作
        await page.check('#my_checkbox')

        # 等待一会儿,以便观察结果
        await asyncio.sleep(3)       

        print('*********page.text,/page.inner,********************')

        # 获取元素的文本内容
        text = await page.text_content('#my_div')
        print("元素的文本内容:", text)

        # 获取元素的内部文本内容
        inner_text = await page.inner_text('#my_div')
        print("元素的内部文本内容:\n", inner_text)

        # 获取元素的内部 HTML 内容
        inner_html = await page.inner_html('#my_div')
        print("元素的内部 HTML 内容:", inner_html)

        # 获取元素的指定属性值
        attribute_value = await page.get_attribute('#my_div', 'class')
        print("元素的 class 属性值:", attribute_value)


        print('***************page.locator********************')
        # 创建一个 Locator 对象
        # locatorx = page.locator('//div[@id="my_div"]')
        locatorx = page.locator('div[id="my_div"]')
        #locatorx = page.locator('.container')
        # locatorx = page.locator('//div')
        # locatorx = page.locator('div.container')
        print(locatorx)

        # 使用列表推导式获取所有匹配元素的内部 HTML 内容
        # all_inner_html = [await  element.inner_html() for element in await locatorx.all()]

        # 获取所有匹配元素的内部 HTML 内容
        all_html = []
        for element in await locatorx.all():
            html_content = await element.inner_html()
            all_html.append(html_content)

        # 打印所有匹配元素的内部 HTML 内容
        for html_content in all_html:
            print(html_content)

        # # 调用 all() 方法获取所有匹配的元素
        # all_elements = await locator.all()

        # # 遍历所有元素并获取它们的内部 HTML 内容
        # for element_locator in all_elements:
        #         inner_html_content = await element_locator.inner_html()
        #         print(inner_html_content)



        print('****************page.query_selector_all*********************')

        # 查询所有匹配选择器的元素
        # async def query_selector_all(self, selector: str) -> List[ElementHandle]:
        #        return await self._main_frame.query_selector_all(selector)
        
        elements = await page.query_selector_all('.container > p')

        # 检查对象是否是 ElementHandle 类型的实例
        if isinstance(elements[0], ElementHandle):
            print("This is an ElementHandle object")

        print(elements)
        # [<JSHandle preview=JSHandle@node>, <JSHandle preview=JSHandle@node>, <JSHandle preview=JSHandle@node>]

        for element in elements:
            # 获取元素的文本内容
            text_content = await element.inner_text()
            print(text_content)  # 去除文本内容两端的空白字符

        print('***************page.evaluate************************')

        # 使用 evaluate执行 JavaScript 代码来获取页面上的 HTML 内容
        html_content = await page.evaluate('document.querySelector(".container").innerHTML')
        #     '''() => {
        #     const container = document.querySelector('.container');
        #     return container.innerHTML;
        # }''')

        # 打印 HTML 内容
        print(html_content)

        print('****************page.evaluate_handle************************')

        # 使用 evaluate_handle 方法执行 JavaScript 代码,获取指定选择器的元素句柄JSHandle
        element_handle = await page.evaluate_handle('document.querySelector(".container")')

        # 获取元素的属性
        # element_class = await element_handle.get_property('className')
        # print(await element_class.json_value())  # 打印元素的 class 属性值  

        text_content = await element_handle.evaluate('(element) => element.textContent')
        print(text_content)




        # 关闭浏览器
        await browser.close()

# 运行主函数
asyncio.run(main())


# 在 Playwright 中,有两种重要的对象类型:ElementHandle 和 JSHandle。
# ElementHandle:
# ElementHandle 代表着一个页面中的 DOM 元素。它是一个指向页面中实际元素的引用,可以让您执行诸如点击、输入等操作,并且可以获取元素的属性、文本内容等信息。
# JSHandle:
# JSHandle 代表着一个 JavaScript 对象,它可能是一个 DOM 元素,也可能是其他 JavaScript 对象。JSHandle 提供了一组方法来执行 JavaScript 代码、获取属性值、执行方法等操作。
# 通常情况下,当您使用 evaluate_handle 方法来执行 JavaScript 代码时,返回的对象可能是一个 ElementHandle 或者是一个 JSHandle,具体取决于执行的 JavaScript 代码以及其返回值类型。
# 如果执行的 JavaScript 代码返回的是一个 DOM 元素,那么返回的就是一个 ElementHandle;
# 如果返回的是其他 JavaScript 对象,那么返回的就是一个 JSHandle。

# 您可以根据返回的对象类型来决定如何进一步操作它。如果返回的是一个 ElementHandle,您可以执行与页面元素相关的操作;
# 如果返回的是一个 JSHandle,您可以执行 JavaScript 对象的操作。
# 通常,您可以使用 instanceof 操作符来检查对象的类型,以便根据需要执行相应的操作。

# DOM(Document Object Model)元素是HTML或XML文档中的一个节点。它可以是文档的根节点、元素节点、文本节点、注释节点等。
# DOM元素在HTML页面中表示页面中的标签,如<div>、<p>、<span>等。
# DOM元素具有以下特点:
# 标签:DOM元素对应于HTML页面中的标签,如<div>、<p>等。
# 属性:DOM元素可以具有属性,这些属性可以包含元素的额外信息或设置,如id、class、style等。
# 子节点:DOM元素可以包含其他元素作为子节点,形成了节点之间的层次结构,如<div>元素可以包含<p>、<span>等作为其子节点。
# 方法和事件:DOM元素有一些方法和事件,可以操作和监听元素的行为和状态。
# 通过使用DOM,可以通过JavaScript或其他脚本语言来访问和操作HTML文档中的元素,比如改变样式、添加新元素、删除元素等。
# DOM提供了一种方便的方式来操作页面结构和内容,并与用户交互。

# Playwright 的页面类(Page)提供的一些用于获取元素信息的异步方法
# async def text_content(
# self, selector: str, strict: bool = None, timeout: float = None
# ) -> Optional[str]:
# return await self._main_frame.text_content(**locals_to_params(locals()))

# async def inner_text(
# self, selector: str, strict: bool = None, timeout: float = None
# ) -> str:
# return await self._main_frame.inner_text(**locals_to_params(locals()))

# async def inner_html(
# self, selector: str, strict: bool = None, timeout: float = None
# ) -> str:
# return await self._main_frame.inner_html(**locals_to_params(locals()))

# async def get_attribute(
# self, selector: str, name: str, strict: bool = None, timeout: float = None
# ) -> Optional[str]:
# return await self._main_frame.get_attribute(**locals_to_params(locals()))

# 用于在指定的元素上输入文本
# await page.type('#my_input', 'Hello, Playwright!')
# async def type(
#     self,
#     selector: str, #要在其上输入文本的元素的选择器
#     text: str,  #要输入的文本内容
#     delay: float = None,
#     timeout: float = None,
#     noWaitAfter: bool = None,
#     strict: bool = None,
# ) -> None:
#     return await self._main_frame.type(**locals_to_params(locals()))

#     def locator(
#         self,
#         selector: str,
#         *,
#         has_text: typing.Optional[typing.Union[str, typing.Pattern[str]]] = None,
#         has_not_text: typing.Optional[typing.Union[str, typing.Pattern[str]]] = None,
#         has: typing.Optional["Locator"] = None,
#         has_not: typing.Optional["Locator"] = None
#     ) -> "Locator":
#         """Page.locator
# page.locator() 是 Playwright 中用于定位元素的方法,它可以通过指定的选择器来选择页面上的元素。
# 在你提供的函数签名中,这个方法还支持一些额外的参数来进一步筛选元素。
# 在你的函数签名中,有以下关键参数:
# selector: str:用于指定要选择的元素的选择器。
# has_text: Optional[Union[str, Pattern[str]]]:可选参数,用于指定元素必须包含特定文本。
# has_not_text: Optional[Union[str, Pattern[str]]]:可选参数,用于指定元素不能包含特定文本。
# has: Optional[Locator]:可选参数,用于指定元素必须符合额外条件。
# has_not: Optional[Locator]:可选参数,用于指定元素不能符合额外条件。
# 使用这些参数,你可以更精确地选择页面上的元素,以满足特定的需求。
# 例如,你可以使用 has_text 参数来找到包含特定文本的元素,或者使用 has 参数来进一步筛选元素。

# async def query_selector_all(self, selector: str) -> typing.List["ElementHandle"]:
#     """Page.query_selector_all
#     The method finds all elements matching the specified selector within the page. If no elements match the selector,
#     the return value resolves to `[]`.

type、press 和 check 方法来模拟用户与页面元素的交互操作

相关推荐
JJJJ_iii7 分钟前
【深度学习05】PyTorch:完整的模型训练套路
人工智能·pytorch·python·深度学习
树叶会结冰8 分钟前
HTML语义化:当网页会说话
前端·html
冰万森14 分钟前
解决 React 项目初始化(npx create-react-app)速度慢的 7 个实用方案
前端·react.js·前端框架
牧羊人_myr27 分钟前
Ajax 技术详解
前端
浩男孩36 分钟前
🍀封装个 Button 组件,使用 vitest 来测试一下
前端
蓝银草同学40 分钟前
阿里 Iconfont 项目丢失?手把手教你将已引用的 SVG 图标下载到本地
前端·icon
布列瑟农的星空1 小时前
重学React —— React事件机制 vs 浏览器事件机制
前端
程序员小远1 小时前
常用的测试用例
自动化测试·软件测试·python·功能测试·测试工具·职场和发展·测试用例
IT学长编程1 小时前
计算机毕业设计 基于EChants的海洋气象数据可视化平台设计与实现 Python 大数据毕业设计 Hadoop毕业设计选题【附源码+文档报告+安装调试】
大数据·hadoop·python·毕业设计·课程设计·毕业论文·海洋气象数据可视化平台