如何在Node.js中高效地进行网页抓取?

我试图从购物网站Express.com刮取一些数据。 以下是许多含有图片价格标题颜色的产品中的一种

<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 scraping库为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); } 

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

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

这种方法很慢,容易出错,而且非常干燥。 我认为如果我们能抓住$('.cat-thu-product')并且使用一个for循环一次提取单个产品的相关信息,那将会很好。

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

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

我build议仍然使用jQuery(因为它很容易,快速和安全)与一个。例子:

 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); 

为了validation您有所有必填字段,您可以编写easillyvalidation器或testing。 但是如果你使用不同的库,你仍然应该循环“div.cat-thu-product”元素。

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

这将是做你正在做的事情的一个好方法。

使用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); })