7.2 While 循环

While 循环

突发性大家不知道本身想循环多少次,而是希望当有个别条件达到规定的标准时或某些检验战败时,退出循环。那些时候就要用while巡回了。斯维夫特提供了三种while循环:

  • do-while循环。用经常的语言表达正是:反复做那件事,直到这件事失利了。do-while连日来第①实施一回代码区域中的代码,然后实施条件语句,假设基准语句为false就退出,不然循环。
  • while
    循环。whiledo-while相形见绌,他会在实施代码区域前先是判断条件语句,如果条件语句true那么才实施代码区域中的代码,反复开始展览这一个进度。

互连网爬虫基本就由如下一些构成:

While

while循环的正经格式如下:

while 条件语句 {
  代码区域
}

while循环首先实施条件语句,假设该语句执行的结果是true才会实施代码区域中的代码,当代码执行结束,回再度判断条件语句,反复实践该流程。与for巡回一样,条件语句必须重返二个布尔类型,非truefalse
大家用时辰候玩的七个蛇形棋的玩乐来介绍while循环。蛇形棋有过多本子,大家前几日玩3个最简便易行的版本。棋盘是5×5四方的,我们从棋盘的左下角初阶,遵照蛇形的依次,在格子里填上数字,从1填到25。格子三巳了有数字,还大概有楼梯。梯子连接了多少个格子,并且梯子只能沿固定的大方向爬。例如大家能够在第壹号格子与第一1号格子建搭建1个梯子,要求只可以从3爬到11,而不能够从11爬回来。以后大家就足以玩了。玩法如下:

  1. 游戏起头时,你把1个意味着你的塑料小人放在1号格子左边的桌面上,那是0号格子的岗位;
  2. 万一你站在25号格子,或然除了0号格子以外的棋盘外,你就大获全胜了,不然执行前边的步骤;
  3. 后天你掷骰子来获取3个[1,6]里面包车型地铁数字;
  4. 您沿着棋盘上数字增大的来头升高该数字个格子,例如你以后在0号格子,掷骰子的数字是6,那么就发展6步,停在6号格子上;要是今后在24号格子,前进6步,就停在30号格子上,固然那些格子在棋盘之外。
  5. 如果还在棋盘上,看看脚下有没有楼梯,倘使有,就本着她爬到接二连三的格子;
  6. 重复执行第壹步。

我们用 Swift模拟一下那些娱乐。之前,我们先转移一下掷骰子的主意。每回掷骰子不是即兴的数字,而是当前的展开的回合数对6的余数加1,那样能够保障每一回的骰子数都以[1,6]中的3个,但不是轻易的。
大家用数组表示这么些棋盘,数组一共有2五个成分,在那之中0号格子在棋盘外面,而[1,25]都在棋盘上。数组成分都起来化为0。

let finalSquare = 25
var board = Int[](count: finalSquare + 1, repeatedValue: 0)

放置了阶梯的格子对应的成分值设置为沿该梯子攀爬时您必要发展或后退的格数(后退用负数表示)。
目前大家在那条蛇身上放置一些梯子。首先从3放3个到11的楼梯,那意味着当你的塑料小人站在第壹号格马时,会爬到11号格子,也正是进步8步,所以给board[3]赋值为8:

board[3] = 8

接下来再放置这个梯子:6->17,9->18,10->12,14->4,19->7,22->20,24->16

board[6] = 11
board[9] = 9
board[10] = 2
board[14] = -10
board[19] = -11
board[22] = -2
board[24] = -9

如此大家用数组的下标表示格子的号子,用数组成分的值表示梯子指向的格子。未来得以初步玩了:

var square = 0
var turns = 0
while square < finalSquare {
  // 掷骰子
  var diceRoll = turns % 6 + 1
  // 前进骰子数个格子
  square += diceRoll
  if square < board.count {
    // 如果我们还在棋盘上,沿着梯子爬吧!
    square += board[square]
  }
  // 回合数增加1
  ++turns
}
println("You win after \(turns + 1) turns")

那段代码会输出

You win after 11 turns

  请求模块方面,小编只想抓取百度的页面,还有天涯论坛的页面,它们的伸手都以https协议的,万幸Node的https和http模块作用差不多是一样的,那里须求做的便是熟知它的api就好了,也是easy。

Do-While

do-whilewhile今非昔比,他老是先举行一段代码然后才看清标准的合法性。
我们用do-while来玩蛇形棋的31日游

let finalSquare = 25
var board = Int[](count: finalSquare + 1, repeatedValue: 0)
board[3] = 8
board[6] = 11
board[9] = 9
board[10] = 2
board[14] = -10
board[19] = -11
board[22] = -2
board[24] = -9

var square = 0
var turns = 0
do {
  // 爬梯子
  square += board[square]
  // 掷骰子
  var diceRoll = turns % 6 + 1
  // 前进骰子数个格子,在这种写法中
  square += diceRoll
  // 回合数增加1
  ++turns
} while square < finalSquare
println("You win after \(turns + 1) turns")

本次大家大概修改了须臾间戏耍的流程:

  1. 玩耍开端时,你把一个代表你的塑料小人放在1号格子左侧的桌面上,那是0号格子的职分;
  2. 今昔检查你日前有没有楼梯,假使有楼梯,就本着她爬到连年的格子;
  3. 下一场掷骰子,获取[1,6]时期的二个数字;
  4. 本着棋盘上数字增大的可行性提升该数字个格子,例如你今后在0号格子,掷骰子的数字是6,那么就迈入6步,停在6号格子上;假如今后在24号格子,前进6步,就停在30号格子上,即便这些格子在棋盘之外。
  5. 倘使您站在第三5号格子或棋盘外,你就大获全胜了,不然重复执行第三步。

次第入口

  开端铺排和起首花commander,具体的接纳办法参考官方的文书档案:https://www.npmjs.com/package/commander,那里不再详细表明用法了,上边起头布局commander。
  首先要在package.json添加如下节点,表示注册了三个限令行 “grab”。

  "bin": {
    "grab": "bin/grab.js"
  },

  接着在grab.js发轫定义commander,最终我们就能够如此实践命令行:”grab
baidu
“,当然能够用bd简写代替baidu,乐乎的定义和百度是均等,那里不再另行介绍了。

    program
        // .allowUnknownOption()//不报错误
        .version('0.0.1')
        .usage('这是我的网络爬虫程序😎'
          +'\n  grap [option]'
          +'\n    bd baidu: baidu search'
          +'\n    zh zhihu: zhihu search');

    program
        .command('baidu <cmd>')
        .alias('bd')
        .description('baidu search baidu')
        .option("-t, --tieba", "baidu tieba")
        .action(function(cmd, options){
          console.log('baidu search "%s":', cmd);
          request.baiduSearch(cmd);
        }).on('--help', function() {
          console.log('  Examples:');
          console.log();
          console.log('    grab bd    <cmd>');
          console.log('    grab baidu <cmd>');
          console.log();
        });

    program.parse(process.argv);

  程序入口能够用web页面完成,还是能够在网页上出示抓取的多少和剖析结果;可是这一个小编只想把精力花在焦点模块,页面和样式不想花太多精力去弄。所以啊,我就开发个node的命令行工具,那几个比较成熟的正是commander了。

数量表明

  抓取数据之后,大家供给做的正是调用cheerio,以jquery获取dom内容的方法获取结果,并显示出来,当然也得以保存文件或数据库。

  /**
   * 显示结果
   * @param  {[type]} pageNo [description]
   * @param  {[type]} body   [description]
   * @return {[type]}        [description]
   */
  function showBaiduResult(pageNo,body){
    var title,summary,link,
        reg=/<[^<>]+>/g,
        $ = cheerio.load(body,{decodeEntities: false});

    $('#content_left .result').each(function(i,item){
      var $a = $(item).find('h3 a');
      title = $a.html();
      link = $a.attr('href');
      summary=$(item).find('.c-abstract').html();
      if(title){
        console.log(`第${pageNo+1}页 第${i+1}条`);
        console.log(`link: ${link}`.green);
        // console.log(`title: ${title}`);
        console.log('title: ');
        ouputColor(title);
        if(summary){
          // console.log(`summary: ${summary}`);
          console.log('summary: ');
          ouputColor(summary);
        }
      }
      console.log('------------------------------');
      console.log('');
    });
  }

  // 知乎
  exports.zhihuSearch=function(keyword,cb){
    get('https://www.zhihu.com/search?type=content&q='+keyword,function(content){
      var title,summary;
      var $ = cheerio.load(content,{decodeEntities: false});
      saveFile(0,keyword,content);
      $('.list .item').each(function(i,item){
        title=$(item).find('.js-title-link').html();
        summary=$(item).find('.summary').html();
        if(title){
          // title=(''+title).replace(/<[^<>]+>/g,'');
          // summary=(''+summary).replace(/<.+>/g,'');
          console.log('title: ');
          ouputColor(title);
          if(summary){
            console.log('summary: ');
            ouputColor(summary);
          }
        }
        console.log('------------------------------');
        console.log('');
      });
    });
  };

进行爬虫

功能完结后,先试验须臾间抓取博客园的内容

grab zh webgl

抓取到的html文件保留在download文件夹,同时在命令行展现抓取结果。
图片 1

若果要执行百度的爬虫,运转如下命令行即可

grab bd webgl
  1. 先后入口
  2. 请求模块
  3. 多少表达

伸网络模特块

  https模块发起呼吁重要有二种艺术,那里稍微封装了下:

  1. get格局,首要针对的是大致的伸手,只供给传递url发起get请求。微博的调用那一个就能够了。

    function get(url,callback) {
        return https.get(url,function(response) {
            var body = '';
    
            response.on('data', function(data) {
                body += data;
            });
    
            response.on('end', function() {
                callback(body);
            });
        });
    }
    
  2. requerst格局,不但能够发起get请求,也能够倡导post请求,还是能修改端口,请求header。那么些第三是指向限制比较多的百度爬虫。百度务必设置header,同时百度呈请参数也相比复杂,要求特别配备,具体可参考网上的素材。

    function request(options,callback){
        // var postData = qs.stringify({});
        var body,
        req = https.request(options, (res) => {
            console.log('STATUS: ' + res.statusCode);
            // console.log('HEADERS: ' + JSON.stringify(res.headers));
            res.setEncoding('utf8');
            res.on('data', function (chunk) {
                body+=chunk;
            });
            res.on('end',function(){
                callback(body)
            });
        });
    
        req.on('error', function(e) {
            console.log('problem with request: ' + e.message);
        });
    
        // write data to request body
        // req.write(postData);
        req.end();
    }
    
    function baiduRequset(pageNo,pageSize,keyword){
        var path='/s?'+qs.stringify({
            ie:'utf-8',
            f:8,
            rsv_bp:1,
            tn:'baidu',
            rn:pageSize,
            pn:pageNo*pageSize,
            wd:keyword
        }),
        options = {
            hostname: 'www.baidu.com',
            port: 443,
            path: path,
            method: 'GET',
            headers: {
                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
            }
        };
    
        request(options,function(body){
            saveFile(pageNo,keyword,body);
            showBaiduResult(pageNo,body);
        });
    }
    

  页面抓取完,数据也剖析出来了,那就格外简单了,你能够挑选存入数据库只怕写入文件保留。接下来就起来兑现地点的功能模块。

  原版的书文地址:NodeJS互连网爬虫
  网上有很多其余语言平台版本的网络爬虫,比如Python,Java。这怎么能少得了大家神通广大的javascript呢?这些和前边给产品狗开发的批量图片下载配置工具,原理很一般,宗旨便是调用Node的http模块。

总结

  那里完成的是最大旨的爬虫功效,代码请看net_grab

  数听大人注肢体模特块,因为抓取出来的页面内容是字符串,所以能够用正则表明式去匹配,但是如此太费劲了。有没有更好的措施?抓取回来可都以html内容,用jQuery以操作dom的艺术去分析数据不是很有益于嘛,恰好有个服务端的jquery库cheerio。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图