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

如何在Playwright JS测试中遍历指定类的多组dt/dd元素?

问题:Playwright JS抓取网页dt/dd数据不全的解决方法

问题背景

需要抓取目标网站中多个i_d类div内的所有dt和dd对应文本,当前代码仅能获取每组的第一个dt/dd项(Series),需修改代码获取完整的Series、Catalog Codes、Variants信息。

网页HTML结构

<div class="pl-it">
   <div class="i_d">
      <dl>
         <dt class>Series:
         <dd>
            <a href=".....">Province A</a>
         </dd>
         </dt>
         <dt class>Catalog Codes:
         <dd>
            <strong>Mi</strong>
            <strong>CA 1x,</strong>
            "ca 17"
         </dd>
         </dt>
         <dt class>Variants:
         <dd><strong><a>Click to see variants</a></strong></dd>
         </dt>
      </dl>
   </div>
   <div class="i_d">
      <dl>
         <dt class>Series:
         <dd>
            <a href=".....">Province B</a>
         </dd>
         </dt>
         <dt class>Catalog Codes:
         <dd>
            <strong>Fu</strong>
            <strong>DE 2x,</strong>
            "pa 21"
         </dd>
         </dt>
         <dt class>Variants:
         <dd><strong><a>Click to see variants</a></strong></dd>
         </dt>
      </dl>
   </div>
</div>

当前代码

const { test, expect } = require('@playwright/test');

test('homepage has Playwright in title and get started link linking to the intro page', async ({ page }) => {
  await page.goto('https://colnect.com/en/stamps/list/country/38-Canada');

  await expect(page.locator('div#pageContent h1')).toContainText('Stamp catalog › Canada › Stamps')


  const books = await page.$$eval('div.i_d', all_items => {
    const data =[];
    all_items.forEach(book => {
      const label = book.querySelector('dt')?.innerText;
      const name = book.querySelector('dd')?.innerText;
      data.push({ label, name});
    })
    return data;
  });  
  console.log(books);
});

当前输出

[
  {
    label: 'Series:',
    name: 'Province A'
  },
  {
    label: 'Series:',
    name: 'Province B'
  },
]

预期输出

Series: Province A
Catalog Codes: Mi CA 1x, ca17
Variants: Click to see variants

Series: Province B
Catalog Codes: Fu DE 2x, pa21
Variants: Click to see variants

解决方案

修改$$eval内的处理逻辑,遍历每个i_d下的所有dt元素,并匹配对应的dd内容,最后整理成预期格式输出。

修改后的代码

const { test, expect } = require('@playwright/test');

test('scrape full stamp details', async ({ page }) => {
  await page.goto('https://colnect.com/en/stamps/list/country/38-Canada');

  await expect(page.locator('div#pageContent h1')).toContainText('Stamp catalog › Canada › Stamps')

  const items = await page.$$eval('div.i_d', allItems => {
    return allItems.map(item => {
      const details = [];
      // 获取当前item下的所有dt元素
      const dts = item.querySelectorAll('dt');
      dts.forEach(dt => {
        // 获取dt的文本并去除多余空格
        const label = dt.innerText.trim();
        // 获取当前dt下的dd元素文本,处理多余空格和换行
        const value = dt.querySelector('dd')?.innerText.replace(/\s+/g, ' ').trim() || '';
        details.push(`${label} ${value}`);
      });
      // 将当前item的所有详情用换行连接,不同item之间留空行
      return details.join('\n');
    }).join('\n\n');
  });  

  console.log(items);
});

代码说明

  1. 原代码使用querySelector只会获取第一个匹配的dt和dd,改为querySelectorAll遍历所有dt元素。
  2. 对每个dt,获取其内部的dd元素文本,用replace(/\s+/g, ' ')合并多余的空格和换行,保证输出格式整洁。
  3. 将每个i_d下的所有dt/dd对拼接成字符串,不同i_d的内容之间添加空行,最终输出符合预期格式的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 00:05:12