如何用Playwright验证表格行存在并遍历筛选后的表格结果
问题
我正在给一个管理程序凭据的第三方网站写自动化脚本,已经搞定了登录、在搜索框填搜索变量并完成表格筛选,但现在没法遍历表格里显示的筛选结果——返回的是整个表格的数据,不是浏览器里显示的筛选后结果。
我需要实现两个需求:
- 没有匹配结果时,直接退出函数;
- 至少有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会包含所有行,不管是否被隐藏,这就是为什么拿到的是全量数据。
修正步骤
定位数据行而非整个表格
把行定位改成表格下的<tr>元素,排除表头行(一般数据行在<tbody>里):rows = page.locator('table[id="tbl_Customer_Asset__c"] tbody tr')如果表格没有
<tbody>,直接用table[id="tbl_Customer_Asset__c"] tr,但大部分规范表格都会用<tbody>包裹数据行。判断无匹配结果
先检查页面是否显示“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提取「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)添加搜索后等待
搜索后加短时间等待,确保表格筛选完成,避免拿到未更新的旧数据: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
相关产品推荐
相关产品推荐

