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

如何使用Node.js、Axios和Cheerio遍历表格获取日落时间数据

问题

我一整天都在开发网页爬虫,从目标网站获取日期和日落时间。目前已能爬取并显示表格第一行的日期和时间,但刚接触Node.js、Axios和Cheerio,不知道如何遍历整个表格。当前JSON结果只有一个对象,我希望遍历表格后让每一行都成为独立对象,示例如下:

[
  {
   "day": "Tue, Nov 1",
   "time": "5:59:57 pm"
  },
  {
   "day": "Tue, Nov 2",
   "time": "5:55:37 pm"
  },
  {
   "day": "Tue, Nov 3",
   "time": "5:42:47 pm"
  }
]

以下是我目前实现爬取第一行的后端代码:

app.get('/results', function (req, res) {
        axios(url)
            .then(response => {
                const html = response.data
                const $ = cheerio.load(html)
                const days = []

                $('#month', html).each(function () {
                    const day = $('.number', '.day').prop('innerText')
                    const time = $('.sunset', '.day').prop('innerText')
                    days.push({
                        day,
                        time
                    })
                })
                res.json(days)
            })
            .catch(err => console.log(err))
    })

前端显示代码:

const feedDisplay = document.querySelector('#feed')

fetch('http://localhost:8000/results')
    .then(response => { return response.json() })
    // .then(data => console.log(data))
    .then(data => {
        data.forEach(daysaray => {
            const dayItem = `<div><h3>` + daysaray.day +`</h3><p>` + daysaray.time +`</div>`
            feedDisplay.insertAdjacentHTML("beforeend", dayItem)
        })
    })
    .catch(err => console.log(err))

补充:目标表格的HTML结构如下:

<table id="month">
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<tbody><tr class="headers">
<th rowspan="2">Day</th>
<th rowspan="2">Twilight start</th>
<th rowspan="2">Sunrise</th>
<th rowspan="2">Sunset</th>
<th rowspan="2">Twilight end</th>
<th rowspan="2">Day length</th>
<th rowspan="2">Solar noon</th>
<th colspan="2">Nautical twilight</th>
<th colspan="2">Astronomical twilight</th>
</tr>
<tr class="headers">
<th>Start</th>
<th>End</th>
<th>Start</th>
<th>End</th>
</tr>
<tr class="day" rel="2022-11-01">
<th><span class="number">Tue, Nov 1</span></th>
<td>7:19:52 am</td>
<td><span class="sunrise" title="Sunrise time 2022-11-01 in Portland, Multnomah County, Oregon, USA">7:49:10 am</span></td>
<td><span title="Sunset time 2022-11-01 in Portland, Multnomah County, Oregon, USA" class="sunset">5:59:22 pm</span></td>
<td>6:28:40 pm</td>
<td>10:10:12</td>
<td>12:54:16 pm</td>
<td>6:44 am</td>
<td>7:03 pm</td>
<td>6:10 am</td>
<td>7:38 pm</td>
</tr>
<tr class="day" rel="2022-11-02">
<th><span class="number">Wed, Nov 2</span></th>
<td>7:21:11 am</td>
<td><span class="sunrise" title="Sunrise time 2022-11-02 in Portland, Multnomah County, Oregon, USA">7:50:33 am</span></td>
<td><span title="Sunset time 2022-11-02 in Portland, Multnomah County, Oregon, USA" class="sunset">5:57:57 pm</span></td>
<td>6:27:19 pm</td>
<td>10:07:24</td>
<td>12:54:15 pm</td>
<td>6:46 am</td>
<td>7:02 pm</td>
<td>6:11 am</td>
<td>7:36 pm</td>
</tr>
<!-- 剩余表格行省略 -->
</tbody></table>
解决方案

问题出在后端代码的遍历逻辑上——你现在是对整个表格(#month)进行遍历,而不是遍历表格里的每一行(tr.day)。修改方法如下:

修正后端代码

将遍历的选择器改为#month tr.day,并在每次迭代中通过$(this)获取当前行,再在该行内查找对应的日期和日落时间元素:

app.get('/results', function (req, res) {
        axios(url)
            .then(response => {
                const html = response.data
                const $ = cheerio.load(html)
                const days = []

                // 遍历每个class为day的表格行
                $('#month tr.day').each(function () {
                    // $(this)指向当前行,在当前行内查找元素
                    const day = $(this).find('.number').text().trim()
                    const time = $(this).find('.sunset').text().trim()
                    days.push({
                        day,
                        time
                    })
                })
                res.json(days)
            })
            .catch(err => console.log(err))
    })

关键说明

  1. 选择器调整:$('#month tr.day')会选中表格内所有带有day类的数据行,而非整个表格。
  2. 元素查找范围:$(this).find('.number')仅在当前行内查找日期元素,避免全局查找导致重复获取第一行数据的问题。
  3. trim()处理:移除文本内容前后的空格,确保数据整洁。

前端代码优化(可选)

使用模板字符串简化HTML拼接,提升代码可读性:

const feedDisplay = document.querySelector('#feed')

fetch('http://localhost:8000/results')
    .then(response => response.json())
    .then(data => {
        data.forEach(item => {
            const dayItem = `<div><h3>${item.day}</h3><p>${item.time}</p></div>`
            feedDisplay.insertAdjacentHTML("beforeend", dayItem)
        })
    })
    .catch(err => console.log(err))

修改后,后端会返回包含所有日期和日落时间的数组,前端可正确渲染每一条数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 01:40:25