爬虫一例,试用nodejs和superagent爬某购物网站网数据(一)。

本来是要发布在cnblog的,奇葩的是找不到发布入口,上次还发表过一篇文章,现在竟然找不到了,就发在csdn了。

之前经常用nodejs+express搭建http框架,发现其实不用,可以做到简洁的完成自己的需求,参考文档。

https://www.nodebeginner.org/index-zh-cn.html.

https://www.cnblogs.com/coco1s/p/4954063.html.

这个教程如果不用router而是直接调用server.

start_listen()
会有两次调用onRequest的问题。


下面说下项目步骤:

准备阶段的安装nodejs步骤略去,就是网上下载nodejs.msi然后安装到默认目录就行。

1,建立手动目录,d:\myproject\js\monitor_jx

2,打开cmd命令行来到monitor_jx目录,执行一些下载需要使用的模块的命令,

因为公司网络使用npm拉包总是失败,使用cnpm,不过初始化还是可以使用npm,一路回车就行。


3,然后命令行下拉几个对应的modules


这里说下cnpm的安装方法:npm install cnpm -g --registry=https://registry.npm.taobao.org

以上安装的是需要的几个包:

 sa = require('superagent'),
  cheerio = require('cheerio'),
  async = require('async'),
  eventproxy = require('eventproxy');


4,在项目目录下手动建index.js文件,server.js文件,两个目录,modules,router。

modules目录下面建文件product.js,router目录下建route.js文件

index.js文件简单,三行即可。

var server = require("./server");
var router = require("./routers/router");

server.start_listen(router.route);


5,server.js文件如下

var http = require('http');
  objProduct= require('./modules/product'),
  sa = require('superagent'),
  cheerio = require('cheerio'),
  async = require('async'),
  eventproxy = require('eventproxy');
 
var ep = new eventproxy(),
  urlsArray = [], //存放爬取网址
  pageUrls = [],  //存放收集页面网址
  pageNum = 10,  //要爬取的页数总数
  pageItems=40;  //每页的商品数目
  totalPageSkus = [];  

var ep2=new eventproxy();
var nameMap = {}; // Map map = new HashMap();
var allProducts={};
 
for(var i=1 ; i<= pageNum ; i++){
  pageUrls.push('http://list.jiuxian.com/1-0-0-0-0-0-0-0-0-0-0-0.htm?pageNum='+i+'&&area=2');
}
 
// 主start程序
function start(route){
  function onRequest(req, res){  
    // 轮询 所有文章列表页
    res.setHeader('Content-Type', 'text/html; charset=utf-8');
    pageUrls.forEach(function(pageUrl){
      sa.get(pageUrl)
        .end(function(err,pres){
          // pres.text 里面存储着请求返回的 html 内容,将它传给 cheerio.load 之后
          // 就可以得到一个实现了 jquery 接口的变量,我们习惯性地将它命名为 `$`
          // 剩下就都是利用$ 使用 jquery 的语法了
          //<a class="proName" href="*" title="*"
          var $ = cheerio.load(pres.text);
          //var curPageUrls = $('.titlelnk');
          //var curPageNodes=$('li[product-box]');//所以包含“product-box”属性的li元素
          var products=$('.proName');//所有包含class="proName"的元素
          for(var i = 0 ; i < products.length ; i++){
            var goodsUrl=products.eq(i).attr('href');
            var name=products.eq(i).attr('title');
            var reg=/http:\/\/www.jiuxian.com\/goods-(.*?).html/;
            var goodsArr  = goodsUrl.match(reg);
            if(goodsArr.length>0){
              var goodsArr  = goodsUrl.match(reg);
              var sku=goodsArr[1];
              nameMap[sku] = name;//as in java: map.put(key, value);
            }
            ep.emit('GoodsHtml', goodsUrl);
          }
        });
    });//forEach

    ep.after('GoodsHtml', pageNum*pageItems ,function(goodsUrls){
    // 当所有 'BlogArticleHtml' 事件完成后的回调触发下面事件
    // ...
      res.write('<br/>');
      res.write('total goods  is '+goodsUrls.length+'<br/>');
      var skus='';
      var onePageSkus=[];
      var reqPricesUrls=[];
      for(var i=0;i<goodsUrls.length; i++){
        //var goods_url = "http://www.jiuxian.com/goods-10.html";
        var reg=/http:\/\/www.jiuxian.com\/goods-(.*?).html/;
        var url= goodsUrls[i];
        var goodsArr  = url.match(reg);
        var sku='';
        if(goodsArr.length>0){
          sku=goodsArr[1];
        }
        onePageSkus.push(sku);
        if((i+1)%pageItems==0){
          totalPageSkus.push(onePageSkus);
          onePageSkus=[];
        }
      }//for
      if(onePageSkus.length>0){
        totalPageSkus.push(onePageSkus);
        onePageSkus=[];
      }
      res.write('<br/>');
      //res.write('http://list.jiuxian.com/act/selectPriceAndClubPriceByProIds.htm?ids='+skus.join(',')+'<br/>');
      totalPageSkus.forEach(function(onePageSkus){
        var requrl='http://list.jiuxian.com/act/selectPriceAndClubPriceByProIds.htm?ids='+onePageSkus.join(',');
        reqPricesUrls.push(requrl);
        //res.write(url+'<br/>');
      });
     
      var curCount = 0;
      var funcReqOnePagePrice = function(url,callback){
      //延迟毫秒数
      var delay = parseInt((Math.random() * 30000000) % 1000, 10);
      curCount++;
      console.log('现在的并发数是', curCount, ',正在抓取的是', ',耗时' + delay + '毫秒'); 
      sa.get(url)
          .end(function(err,sres){
              var $ = cheerio.load(sres.text);
              var data = sres.text;
              var obj = JSON.parse(data);
              // res.write('status'+obj.status+"<br/>");
                //解析数组
              obj.data.forEach(function(item) {
              var clubPrice=0.0;
              var price=0.0;
              if (typeof(item.clubPrice) != 'undefined') {
                clubPrice=parseFloat(item.clubPrice);
              }
              if(typeof(item.price) != 'undefined'){
                price=parseFloat(item.price);
              }
              var name='';
              if(typeof(nameMap[item.productId])!='undefined'){
                name=nameMap[item.productId];
              }
              var p=objProduct.createProduct(item.productId,price,clubPrice);
              p.name=name;
              allProducts[item.productId]=p;
              res.write(p.name+':'+
                clubPrice + 
                "," + item.price    +
                ",id:" + item.productId + '<br/>');
            });
          });
          setTimeout(function() {
              curCount--;
              callback(null,url +'Call back content');
              console.log('剩余请求数为:'+curCount);
          }, delay);     
      };
      // 使用async控制异步抓取   
      // mapLimit(arr, limit, iterator, [callback])
      // 异步回调
      async.mapLimit(reqPricesUrls, 10 ,function (url, callback) {
        funcReqOnePagePrice(url, callback);
        }, function (err,result) {
         // pageNum 个 URL 访问完成的回调函数
         console.log('抓取结束');
      }); 
    })//after
  };//onRequest
  http.createServer(onRequest).listen(3000);
}
exports.start_listen= start;



6,route.js文件如下

function route(pathname) {
    console.log("About to route a request for " + pathname);
  }
  
  exports.route = route;
7,product.js文件如下

function createProduct(productId,price,clubPrice) {
    var oTempProduct = new Object;
    oTempProduct.proId = productId;
    oTempProduct.proPrice = price;
    oTempProduct.proClubPrice = clubPrice;
    oTempProduct.name='';
    return oTempProduct;
  }

  exports.createProduct= createProduct;//暴露出来才能在外面使用


8。文件建立完毕,命令行执行node index,然后浏览器里输入 http://localhost:3000/

命令行打印如下。


网页显示的一部分如下



主要工作在server.js里面,代码分析有时间再写一篇文章。

这只是初步工作剩下还有存储历史数据和定时刷新比较出新低价的工作未做。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值