首页 > 解决方案 > 将 puppeteer json 写入 html 中的 html 表中并在没有 jQuery 的情况下保存

问题描述

我将网站上的标题和图像收集成人类可读的格式。

我使用fs.writeFile和选项是:

  1. 另存为 html(在本地打开)或者,
  2. 让它通过nodemailer发送到电子邮件。

无论哪种方式,我都需要 html 中表格格式的信息。顶行 = 标题、价格、图片(显示,而非链接)。列 = 项目列表。

我添加了一部分以将 JSON 转换为 html 表,但它搞砸了。现在脚本没有运行。错误是文档未定义(以表格形式)。

另外,如果有任何方法可以在不维护服务器的情况下每天将列表自动发送到电子邮件,也请告诉我。

const puppeteer = require('puppeteer');
const fs = require('fs');

/* this gets the json data, all working ok */
async function newCam() {
   const browser = await puppeteer.launch({ headless: false });
   let page = await browser.newPage();
   await page.goto('https://sg.carousell.com/search/products/?query=camera', { waitUntil: 'networkidle2' });
   let results = []; 
   let elements = await page.$$('div.U-U');
   for (let element of elements) {
      let listTitle  = await element.$eval('div.U-m', node => node.innerText.trim());
      let listImg    = await element.$eval('.U-p img', img => img.src);
      let listPrice  = await element.$eval('div.U-k :nth-child(1)', node => node.innerText.trim());
      results.push({ 
         'Title': listTitle,
         'Img':   listImg,
         'Px':    listPrice 
      });
   }
   await browser.close();
   return results;


   /* format json into table and feed into fs below */
      // get header keys
      var col = [];
      for (var i = 0; i < results.length; i++) {
         for (var key in results[i]) {
               if (col.indexOf(key) === -1) { col.push(key); }
         }
      }

      // create table 
      var table = document.createElement("table");
      var tr = table.insertRow(-1);                   // insert header row.
      for (var k = 0; k < col.length; k++) {
         var th = document.createElement("th");      // fill header
         th.innerHTML = col[k];
         tr.appendChild(th);
      }
      // add json data as rows
      for (var a = 0; a < results.length; a++) {
         tr = table.insertRow(-1);
         for (var f = 0; f < col.length; f++) {
               var tabCell = tr.insertCell(-1);
               tabCell.innerHTML = results[a][col[f]];
         }
      }

   /* save to html on local drive with fs */ 
   fs.writeFile('/data.html', table, (err) => {
      if (err) throw err;
   });
}
newCam();

标签: javascripthtmlnode.jspuppeteer

解决方案


为什么您的代码不起作用

您正在尝试在 Node.js 环境中使用 DOM。Node.js 在服务器端执行 JavaScript。因此没有您可以访问的 DOM 变量(如windowor document)。因此你得到了错误document is not defined

有关该主题的更多信息,您可能需要查看“为什么 Node.js 没有本机 DOM?”这个问题。

表创建

如果您想创建 HTML 表格的标记,您可以使用字符串连接并将表格简单地合并在一起,或者使用jsdom 之类的东西在服务器端模拟 DOM。

由于您的情况似乎很简单,我会选择第一个选项。

这里有一些相当简单的代码来为表格创建 HTML 标记。您可以将它放入您的代码而不是“创建表”代码中,它会生成一个表,其中每个值对应一列col

function escapeHtml(str) { // for security reasons escape "<" (you could even improve this)
    return str.replace(/</g, '&lt;');
}

const htmlTable = '<table>'
    + `\n <tr>${col.map(c => '<th>' + escapeHtml(c) + '</th>')}</tr>`
    + results // generate rows, use map function to map values to trs/tds
        .map(row => ('\n <tr>' +
            col.map(c => `\n  <td>${escapeHtml(row[c])}</td>`).join('')
        + '\n</tr>')).join('')
    + '\n</table>';

fs.writeFile('/data.html', htmlTable, (err) => {
    // ...
});

当然,此代码是一个相当简单的示例,可以帮助您入门。

通过邮件发送文件

除了在本地保存 HTML,您还可以使用 nodemailer 直接通过邮件发送。这是一个帮助您入门的代码示例,但您可能需要查看nodemailer 网站以获取更多信息。

await transporter.sendMail({
    /* ... */
    html: 'Full HTML document.... ' + htmlTable + ' ...'
});

推荐阅读