【问题标题】:How to efficiently do web scraping in Node.js?如何在 Node.js 中高效地进行网页抓取?
【发布时间】:2013-01-15 05:48:57
【问题描述】:

我正在尝试从购物网站 Express.com 上抓取一些数据。这是包含 imagepricetitlecolor(s) 的众多产品中的 1 个。

  <div class="cat-thu-product cat-thu-product-all item-1">
<div class="cat-thu-p-cont reg-thumb" id="p-50715" style="position: relative;"><a href="/rocco-slim-fit-skinny-leg-corduroy-jean-50715-647/control/show/3/index.pro" onclick="var x=&quot;.tl(&quot;;s_objectID=&quot;http://www.express.com/rocco-slim-fit-skinny-leg-corduroy-jean-50715-647/control/show/3/index.pro_1&quot;;return this.s_oc?this.s_oc(e):true"><img class="cat-thu-p-ima widget-app-quickview" src="http://t.express.com/com/scene7/s7d5/=/is/image/expressfashion/25_323_2516_900/i81?$dcat191$" alt="ROCCO SLIM FIT SKINNY LEG CORDUROY JEAN"></a><a href="#jsLink"><img id="widget-quickview-but" class="widget-ie6png glo-but-css-off2" src="/assets/images/but/cat/but-cat-quickview.png" alt="Express View" style="position: absolute; left: 50px;"></a></div>
  <ul>
    <li class="cat-cat-more-colors">
      <div class="productId-50715">
        <img class="js-swatchLinkQuickview" title="INK BLUE" src="http://t.express.com/com/scene7/s7d5/=/is/image/expressfashion/25_323_2516_900_s/i81?$swatch$" width="16" height="6" alt="INK BLUE">
        <img class="js-swatchLinkQuickview" title="GRAPHITE" src="http://t.express.com/com/scene7/s7d5/=/is/image/expressfashion/25_323_2516_924_s/i81?$swatch$" width="16" height="6" alt="GRAPHITE">
        <img class="js-swatchLinkQuickview" title="MERCURY GRAY" src="http://t.express.com/com/scene7/s7d5/=/is/image/expressfashion/25_323_2516_930_s/i81?$swatch$" width="16" height="6" alt="MERCURY GRAY">
        <img class="js-swatchLinkQuickview" title="HARVARD RED" src="http://t.express.com/com/scene7/s7d5/=/is/image/expressfashion/25_323_2516_853_s/i81?$swatch$" width="16" height="6" alt="HARVARD RED">
      </div>
    </li>
    <li class="cat-thu-name"><a href="/rocco-slim-fit-skinny-leg-corduroy-jean-50715-647/control/show/3/index.pro" onclick="var x=&quot;.tl(&quot;;s_objectID=&quot;http://www.express.com/rocco-slim-fit-skinny-leg-corduroy-jean-50715-647/control/show/3/index.pro_2&quot;;return this.s_oc?this.s_oc(e):true">ROCCO SLIM FIT SKINNY LEG CORDUROY JEAN
    </a></li>
    <li>
      <strong>$88.00</strong>
    </li>
  <li class="cat-thu-promo-text"><font color="BLACK" style="font-weight:normal">Buy 1, Get 1 50% Off</font>
  </li>
</ul>

我所做的非常幼稚且可能容易出错的方法是首先获取所有价格、图像、标题和颜色:

var price_objects = $('.cat-thu-product li strong');
var image_objects = $('.cat-thu-p-ima');
var name_objects = $('.cat-thu-name a');
var color_objects = $('.cat-cat-more-colors div');

接下来,我使用 jsdomcheerio 为 node.js 抓取库从 DOM 中提取的数据填充数组。 (在这种情况下是 Cheerio)。

  // price info
  for (var i = 0; i < price_objects.length; i++) {
    prices.push(price_objects[i].children[0].data);
  }
  // image links
  for (var i = 0; i < image_objects.length; i++) {
    images.push(image_objects[i].attribs.src.slice(0, -10));
  }
  // name info
  for (var i = 0; i < name_objects.length; i++) {
    names.push(name_objects[i].children[0].data);
  }
  // color info
  for (var i = 0; i < color_objects.length; i++) {
    colors.push(color_objects[i].attribs.src);
  }

最后,基于价格、标题、图像和颜色匹配的假设创建一个产品对象:

for (var i = 0; i < images.length; i++) {
  items.push({
    id: i,
    name: names[i],
    price: prices[i],
    image: images[i],
    colors: colors[i]
  });
}

这种方法速度慢,容易出错,而且非常抗 DRY。我在想,如果我们能抓住 $('.cat-thu-product') 并使用单个 for 循环从单个产品中提取相关信息,那就太好了。

但是你有没有试过在 jsdomcheerio 中遍历 DOM?我不知道任何人甚至可以理解它。有人可以通过抓取包含所有相关信息的$('.cat-thu-product') div 元素然后提取必要的数据来展示我将如何使用这种建议的抓取方法吗?

或者也许有更好的方法来做到这一点?

【问题讨论】:

    标签: node.js web-scraping jsdom cheerio


    【解决方案1】:

    我建议仍然使用 jQuery(因为它简单、快速且安全)和一个 .each 示例:

    var items = [];
    $('div.cat-thu-product').each(function(index, productElement) {
      var product = {
        id: $('div.cat-thu-p-cont', productElement).attr('id'),
        name: $('li.cat-thu-name a', productElement).text().trim(),
        price: $('ul li strong', productElement).text(),
        image: $('.cat-thu-p-ima', productElement).attr('src'),
        colors: []
      };
      // Adding colors array
      $('.cat-cat-more-colors div img', productElement).each(function(index, colorElement) {
        product.colors.push({name: $(colorElement).attr('alt'), imageUrl: $(colorElement).attr('src')});
      });
    
      items.push(product);
    });
    
    console.log(items);
    

    为了验证您是否拥有所有必填字段,您可以编写简单的验证器或测试。但是如果你使用不同的库,你仍然应该遍历“div.cat-thu-product”元素。

    【讨论】:

    • 谢谢,除了更好的解决方案之外,您还解决了我获取颜色数组的问题。
    【解决方案2】:

    试试 node.io https://github.com/chriso/node.io/wiki

    这将是做你想做的事情的好方法。

    【讨论】:

      【解决方案3】:

      使用https://github.com/rc0x03/node-promise-parser

      products = []; 
      pp('website.com/products')
       .find('div.cat-thu-product')
       .set({
           'id':       'div.cat-thu-p-cont @id',
           'name':     'li.cat-thu-name a',
           'price':    'ul li strong',
           'image':    '.cat-thu-p-ima',
           'colors[]': '.cat-cat-more-colors div img @alt',
       })
       .get(function(product) {
          console.log(product);
          products.push(product);
       })
      

      【讨论】:

        猜你喜欢
        • 2016-08-25
        • 2017-06-23
        • 2015-10-23
        • 1970-01-01
        • 1970-01-01
        • 2021-07-06
        • 1970-01-01
        • 2020-08-25
        • 2018-02-24
        相关资源
        最近更新 更多