【问题标题】:Scraping web data into multiple HTML tables?将 Web 数据抓取到多个 HTML 表格中?
【发布时间】:2020-10-07 13:23:07
【问题描述】:

*cmets 中的更多详细信息

我正在使用 Cheerio.js 来抓取数据并显示在 3 个 HTML 表格中。它运行正常,除了第 2 和第 3 表在显示抓取的数据之前添加了这些空白行(第 1 表有 25 行,第 2 表有 25 行,然后是 25 行数据。第 3 表有 50 行,然后是 25 行数据)。

我相信这是由于通过一个请求抓取所有数据,而不是对每个表进行 1 次抓取。

这是我第一次抓取,所以我想知道是否有办法可以更改我的代码来解决这个问题,或者我是否必须对每个表有 1 个抓取请求(但这似乎效率低下)。

如果您想查看我的 mongoose 架构,请告诉我。

显示数据的HTML表格(使用ejs):

<table>
          <tr>
              <th>Environment</th>
              <th>Store Name</th>
              <th>Code Version</th>
          </tr>
      <% stores.forEach(function(store){ %>

          <tr>
              <td> <%= store.environment.QA1 %> </td>
              <td> <%= store.store.QA1 %> </td>
              <td> <%= store.version.QA1 %> </td>
          </tr>
      <% }); %>
  </table>

cheerio.js 抓取信息:

router.get("/scrape", function(req, res){
    request("http://link-goes-here", function(error, response, html){
        var $ = cheerio.load(html);
        var QAStoreInfo = [];
        var QA1StoreInfo = [];
        
        $("body > table > tbody > tr > td:nth-child(1) > table").addClass("row");
        $('.row > tbody > tr:contains("QA")').each(function(i, element){
            var QAResult = {
                "environment.QA" : $(this).children().next(),
                "store.QA" : $(this).children().next().next(),
                "version.QA" : $(this).children().next().next().next()
            };
            QAStoreInfo.push(QAResult);
             Store.count({}, function(err, test){
                if (test === 0) {
                    var QAEntry = new Store(QAResult);
    
                    QAEntry.save(function(err, doc){
                        if(err){
                            console.log(err);
                        }
                    });
                }
             });
        });

        /* QA1 */
        $('.row > tbody > tr:contains("QA1")').each(function(i, element){
            var QA1Result = {
                "environment.QA1" : $(this).children().next(),
                "store.QA1" : $(this).children().next().next(),
                "version.QA1" : $(this).children().next().next().next()
            };

            QA1StoreInfo.push(QA1Result);
             Store.count({}, function(err, test){
                if (test === 0) {
                    var QA1Entry = new Store(QA1Result);
   
                    QA1Entry.save(function(err, doc){
                        if(err){
                            console.log(err);
                        }
                    });
                }
             });
        });

猫鼬模式:

var storeSchema = new mongoose.Schema({
  environment: {
    QA: String,
    QA1: String,
    QA2: String
  },
  store: {
    QA: String,
    QA1: String,
    QA2: String
  },
  version: {
    QA: String,
    QA1: String,
    QA2: String
  }
});

/scrape 调用后的 mongoDB 集合:

{ "_id" : ObjectId("5f0610fee9b4c35d74a83600"), "environment" : { "QA1" : " QA1 " }, "store" : { "QA1" : " Omega  QA " }, "version" : { "QA1" : " _2019.11_2019_11.2 " }, "__v" : 0 }
{ "_id" : ObjectId("5f0610fee9b4c35d74a83601"), "environment" : { "QA1" : " QA1 " }, "store" : { "QA1" : " Crescent Centre " }, "version" : { "QA1" : " _2020.06_2020_06.6 " }, "__v" : 0 }
{ "_id" : ObjectId("5f0610fee9b4c35d74a83602"), "environment" : { "QA1" : " QA1 " }, "store" : { "QA1" : " Cumberland " }, "version" : { "QA1" : " _2019.11_2019_11.2 " }, "__v" : 0 }
{ "_id" : ObjectId("5f0610fee9b4c35d74a83603"), "environment" : { "QA1" : " QA1 " }, "store" : { "QA1" : " East Denver " }, "version" : { "QA1" : " _2019.11_2019_11.2 " }, "__v" : 0 }
{ "_id" : ObjectId("5f0610fee9b4c35d74a83604"), "environment" : { "QA1" : " QA1 " }, "store" : { "QA1" : " Brookwood " }, "version" : { "QA1" : " _2019.11_2019_11.2 " }, "__v" : 0 }
{ "_id" : ObjectId("5f0610fee9b4c35d74a83605"), "environment" : { "QA1" : " QA1 " }, "store" : { "QA1" : " WheatRidge  " }, "version" : { "QA1" : " _2019.11_2019_11.2 " }, "__v" : 0 }
{ "_id" : ObjectId("5f0610fee9b4c35d74a83606"), "environment" : { "QA1" : " QA1 " }, "store" : { "QA1" : " Aurora Centerpoint  " }, "version" : { "QA1" : " _2020.06_2020_06.6 " }, "__v" : 0 }
{ "_id" : ObjectId("5f0610fee9b4c35d74a83607"), "environment" : { "QA1" : " QA1 " }, "store" : { "QA1" : " Castle Rock  " }, "version" : { "QA1" : " _2020.06_2020_06.6 " }, "__v" : 0 }
{ "_id" : ObjectId("5f0610fee9b4c35d74a83608"), "environment" : { "QA1" : " QA1 " }, "store" : { "QA1" : " Conyers  " }, "version" : { "QA1" : " _2020.06_2020_06.6 " }, "__v" : 0 }

屏幕截图:(第二张表的显示方式)

【问题讨论】:

  • 您介意详细说明一下吗?如果我理解错误,请纠正我,但看起来您发布的服务器端代码基本上将新商店保存到您的数据库中?你贴的这些表是什么?他们在你的应用程序上吗?他们从哪里获取数据?在 /scrape 调用之后,您的收藏看起来如何?
  • @TomSlabbaert 是的!所以我使用cheerio 从网站上抓取数据(出于隐私原因未包含在代码中),然后我将这些数据存储到数据库中。然后我将数据库中的信息显示到我的应用程序的 html 表中。屏幕截图是 HTML 代码生成的示例。如果您想查看,我还添加了我的猫鼬模式...如果您有更多问题,请告诉我
  • @TomSlabbaert 我还添加了部分集合在抓取调用后的外观
  • 看起来就像您将空对象保存到数据库中(或者它们已经存在)。
  • 您可以在将行的值实际存储到数据库之前检查该行的值是否不为空。

标签: node.js mongodb web-scraping html-table cheerio


【解决方案1】:

Store 集合包含具有以下架构的抓取文档:

{
    "environment" : { "QA":  <string> } ,  
    "store" : { "QA": <string> },
    "version" :  { "QA": <string> }
}

{
    "environment" : { "QA1":  <string> } ,  
    "store" : { "QA1": <string> },
    "version" :  { "QA1": <string> }
}

HTML 表中的空行用于记录具有第一个模式的记录,其中environmentstoreversion 文档字段中的QA1undefined

我建议将Store 文档的架构与以下架构协调一致:

{
    "kind": "QA|QA1",
    "environment" : <string> ,  
    "store" : <string> ,
    "version" :  <string>
}

然后更新您的爬虫脚本以存储文档,如下所示:

//...
            var QAResult = {
                "kind": "QA",
                "environment" : $(this).children().next(),
                "store" : $(this).children().next().next(),
                "version" : $(this).children().next().next().next()
            };
            QAStoreInfo.push(QAResult);
 
//...

            var QA1Result = {
                "kind": "QA1",
                "environment" : $(this).children().next(),
                "store" : $(this).children().next().next(),
                "version" : $(this).children().next().next().next()
            };

            QA1StoreInfo.push(QA1Result);

ejs 模板中的forEach 循环可以更新如下:

     <% stores.forEach(function(store){ %>

          <tr>
              <td> <%= store.environment %> </td>
              <td> <%= store.store %> </td>
              <td> <%= store.version %> </td>
          </tr>
      <% }); %>

【讨论】:

  • 感谢您的帮助!刚刚遇到了一些计算机问题,现在无法设置所有备份,所以我暂时无法测试它..但是赏金是你的!
  • 不用担心。当你回来测试它并且这个答案解决了问题时,你能把它标记为你的问题的答案吗?
猜你喜欢
  • 2017-12-22
  • 1970-01-01
  • 2018-04-27
  • 2018-02-24
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
相关资源
最近更新 更多