You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Playwright验证表格行存在并遍历筛选后的表格结果

问题

我正在给一个管理程序凭据的第三方网站写自动化脚本,已经搞定了登录、在搜索框填搜索变量并完成表格筛选,但现在没法遍历表格里显示的筛选结果——返回的是整个表格的数据,不是浏览器里显示的筛选后结果。

我需要实现两个需求:

  1. 没有匹配结果时,直接退出函数;
  2. 至少有1个匹配结果时,遍历表格行,把「Key Name」的值存到变量里。

我查过Playwright的locators文档,但Lists部分的代码跑不起来。

我的代码如下:

def deactivate_current_license(page, email_address):
    print(f"Searching for currently assigned licenses for {email_address}")
    
    page.locator('text=Search: >> input[type="search"]').fill(email_address)
    page.locator('text=Search: >> input[type="search"]').press("Enter")

    # Locate elements, this locator points to a list.
    rows = page.locator('table[id="tbl_Customer_Asset__c"]')

    # Pattern 3: resolve locator to elements on page and map them to their text content.
    # Note: the code inside evaluateAll runs in page, you can call any DOM apis there.
    texts = rows.evaluate_all("list => list.map(element => element.textContent)")

表格三种场景显示:

  • 无匹配结果:无匹配结果
  • 单个匹配结果:单个匹配结果
  • 多个匹配结果:多个匹配结果

解决方案

问题根源

你现在的rows定位的是整个表格,而非表格里的数据行。另外很多网站的筛选是前端通过隐藏不匹配行实现的,直接获取表格的textContent会包含所有行,不管是否被隐藏,这就是为什么拿到的是全量数据。

修正步骤

  1. 定位数据行而非整个表格
    把行定位改成表格下的<tr>元素,排除表头行(一般数据行在<tbody>里):

    rows = page.locator('table[id="tbl_Customer_Asset__c"] tbody tr')
    

    如果表格没有<tbody>,直接用table[id="tbl_Customer_Asset__c"] tr,但大部分规范表格都会用<tbody>包裹数据行。

  2. 判断无匹配结果
    先检查页面是否显示“No records to display”这类无结果提示,直接判断其可见性:

    no_results = page.locator('text="No records to display"')
    if no_results.is_visible():
        print(f"No licenses found for {email_address}")
        return
    
  3. 提取「Key Name」值
    为了避免列顺序变化导致提取错误,先通过表头找到「Key Name」对应的列索引,再遍历每一行提取对应列的内容:

    # 获取Key Name列的索引
    header_index = page.locator('table[id="tbl_Customer_Asset__c"] th').evaluate_all(
        "(headers, target) => headers.findIndex(h => h.textContent.trim() === target)", "Key Name"
    )
    if header_index == -1:
        print("Key Name column not found")
        return
    
    # 遍历可见行提取值
    key_names = []
    row_count = rows.count()
    for i in range(row_count):
        key_name = rows.nth(i).locator('td').nth(header_index).text_content().strip()
        key_names.append(key_name)
    
  4. 添加搜索后等待
    搜索后加短时间等待,确保表格筛选完成,避免拿到未更新的旧数据:

    page.locator('text=Search: >> input[type="search"]').press("Enter")
    page.wait_for_timeout(500)  # 可根据网站加载速度调整,或用更精准的元素等待
    

完整修正代码

def deactivate_current_license(page, email_address):
    print(f"Searching for currently assigned licenses for {email_address}")
    
    search_input = page.locator('text=Search: >> input[type="search"]')
    search_input.fill(email_address)
    search_input.press("Enter")

    # 等待筛选结果加载完成
    page.wait_for_timeout(500)

    # 处理无匹配结果场景
    no_results = page.locator('text="No records to display"')
    if no_results.is_visible():
        print(f"No licenses found for {email_address}")
        return

    # 定位表格数据行
    rows = page.locator('table[id="tbl_Customer_Asset__c"] tbody tr')
    row_count = rows.count()
    if row_count == 0:
        print(f"No licenses found for {email_address}")
        return

    # 获取Key Name列的索引
    header_index = page.locator('table[id="tbl_Customer_Asset__c"] th').evaluate_all(
        "(headers, target) => headers.findIndex(h => h.textContent.trim() === target)", "Key Name"
    )
    if header_index == -1:
        print("Key Name column not found")
        return

    # 遍历行提取Key Name值
    key_names = []
    for i in range(row_count):
        key_name = rows.nth(i).locator('td').nth(header_index).text_content().strip()
        key_names.append(key_name)

    print(f"Found Key Names: {key_names}")
    return key_names

额外提示

  • 如果网站筛选是后端接口返回结果(不是前端隐藏行),直接定位行即可,无需额外处理可见性;
  • 用text_content()时记得加strip(),避免提取到多余空格;
  • 固定等待时间可以替换为page.wait_for_selector,比如等待数据行出现,这样更可靠:rows.first.wait_for()

内容的提问来源于stack exchange,提问作者swolfe2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 14:35:57