【问题标题】:Extracting Multiple Child Elements from a Parent using Cheerio使用 Cheerio 从父元素中提取多个子元素
【发布时间】:2022-11-26 12:19:43
【问题描述】:

我正在尝试使用 Cheerio 来抓取数据并最终将生成的 HTML 转换为 Markdown。

虽然不是这个问题的核心,但要转换为 Markdown,我只需要一些有效的 HTML。具体来说,对于这种情况,一个带有一个或多个<ul> 标签的 div。

我提到这一点,所以很明显我没有使用生成的 HTML 直接呈现,但我需要它以一种可用于转换为 Markdown 的形式。

使用下面的简化示例并给定一个已知的类名“things”,父 div 中有两个 <ul> 标签。

请注意,ul 标签在我抓取的代码中没有类或 ID。

<div class="things"> // <= want
    <h5 class="heading">Things</h5> // <= don't want
    <ul> // <= want with children
        <li class="sub-heading">Fruits</li>
        <li class="fruit-item">Apple</li>
        <li class="fruit-item">Pear</li>
    </ul>
    <ul> // <= want with children
        <li class="sub-heading">Veg</li>
        <li class="veg-item">Carrot</li>
        <li class="veg-item">Spinach</li>
    </ul>
</div>

我希望每个ul 的列表项都在div 周围。

以下结果 HTML 没有周围的 div 和我不想要的东西(例如 &lt;h5 class="heading"&gt;Things&lt;/h5&gt;):

const stuffIWant = $(".things").html();

以下结果 HTML 没有周围的 div,只有 &lt;ul&gt; 标签之一的内容,而不是 ul 本身:

const stuffIWant = $(".things ul").html();

我知道这是因为 .html() 返回第一个元素,所以我只是从第一个 ul 获取列表项。

这是我的问题,也是我让自己感到困惑的地方。

我也尝试过各种形式的过滤器、地图和每一种,但我无法在封闭的div 中返回多个&lt;ul&gt; 标签。

我在想也许我需要使用 eachmap 遍历“事物”div,并将我想要的元素附加到新的 div(不知何故?),但这似乎比它应该的更复杂,所以我在这里问。

任何帮助我解决这个问题的建议都将不胜感激。

谢谢。

【问题讨论】:

  • 也许尝试在每个父级上使用 .find("ul") 而不是 .html 并遍历子级。你想输出什么数据结构?

标签: cheerio


【解决方案1】:

虽然这篇文章没有完全澄清,但似乎有两种解释方式。一种可能性是您希望在一系列数组中为每个 &lt;ul&gt;s 提供所有 &lt;li&gt;s:

const $ = cheerio.load(html);
const result = [...$(".things ul")].map(e =>
  [...$(e).find("li")].map(e => $(e).text())
);
console.log(result);

这使

[
  [ 'Fruits', 'Apple', 'Pear' ],
  [ 'Veg', 'Carrot', 'Spinach' ],
]

现在,如果 &lt;div class="things"&gt; 包装器重复出现并且你想区分这些组中的每一个,你可以修改上面的代码如下:

const cheerio = require("cheerio"); // 1.0.0-rc.12

const html = `
<div class="things">
  <h5 class="heading">Things</h5>
  <ul>
    <li class="sub-heading">Fruits</li>
    <li class="fruit-item">Apple</li>
    <li class="fruit-item">Pear</li>
  </ul>
  <ul>
    <li class="sub-heading">Veg</li>
    <li class="veg-item">Carrot</li>
    <li class="veg-item">Spinach</li>
  </ul>
</div>
<div class="things">
  <h5 class="heading">Things 2</h5>
  <ul>
    <li class="sub-heading">Foo</li>
    <li class="fruit-item">Bar</li>
    <li class="fruit-item">Baz</li>
  </ul>
</div>
`;

const $ = cheerio.load(html);
const result = [...$(".things")].map(e =>
  [...$(e).find("ul")].map(e =>
    [...$(e).find("li")].map(e => $(e).text())
  )
);
console.log(JSON.stringify(result, null, 2));

这给出:

[
  [
    [
      "Fruits",
      "Apple",
      "Pear"
    ],
    [
      "Veg",
      "Carrot",
      "Spinach"
    ]
  ],
  [
    [
      "Foo",
      "Bar",
      "Baz"
    ]
  ]
]

换句话说,有一个额外的层:

- .things
  - ul
    - li

与顶部代码相反,它使.things变平:

- .things ul
  - li

【讨论】:

    猜你喜欢
    • 2016-09-22
    • 1970-01-01
    • 2019-07-21
    • 2023-03-18
    • 1970-01-01
    • 2019-02-19
    • 2016-05-11
    • 2018-12-09
    • 1970-01-01
    相关资源
    最近更新 更多