语言Swift 3 中Private和Fileprivate的分

  原文地址:NodeJS网络爬虫
  网上发无数外语言平台版本的网络爬虫,比如Python,Java。那怎么能够少得矣俺们无所不能的javascript呢?这个与事先给活狗开发的批量图片下载配置工具,原理非常相似,核心就是调用Node的http模块。

当Swift首差引入访问级别时,对之开展了有些歪曲和未知。虽然开发人员对于增长对Swift编程语言的访问控制感到兴奋,但是private首要字的所作所为以及另编程语言的所作所为不同。

网爬虫基本就由如下一些组成:

立当Swift 3中早就来了转,通过丰富其它一个要字展开私有访问控制fileprivate。区别是微妙但是好懂。
  1. 次入口
  2. 恳请模块
  3. 数说明

Swift 3 之前

以引入Swift
3之前,private关键字用实体(类,结构,枚举,…)的采用范围以概念其的源文件中。看下的例子。

import UIKit

class NotesViewController: UIViewController {

    private var dataSource = [String]()

}

extension NotesViewController: UITableViewDataSource {

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataSource.count
    }

    ...

}

咱们声明一个UIViewController子类NotesViewController,
他带有一个[String]项目的个人属性dataSource。在和一个源于文件中,我们吧NotesViewController类似创建一个扩张,遵守UITableViewDataSource说道。有趣之是咱好拜扩展中的dataSource属性(dataSource.count),即使属性被声称也private

  程序入口可以据此web页面实现,还可以当网页上显得抓取的数据以及剖析结果;但是这自己就想把精力花在基本模块,页面和体不思量花尽多精力去干。所以也,我不怕付出个node的命令行工具,这个比成熟的便是commander了。

Swift3中

一经我们将上述代码有移植到Swift 3,编译器会废弃来一个误。它告诉我们dataSource性是一个未解析的标识符。换句话说,通过将dataSource属性声明也private,扩展名中不可看。

Paste_Image.png

  请求模块方面,我不过想拘捕到手百度的页面,还有知乎的页面,它们的呼吁都是https协议的,好于Node的https和http模块功能几乎是均等的,这里用做的饶是熟悉她的api就吓了,也是easy。

个别只例外之Private:Private 和 filePrivate

  数据说明模块,因为抓取出来的页面内容是字符串,所以可以就此正则表达式去匹配,但是如此太累了。有没起重复好之计?抓到手回来但还是html内容,用jQuery以操作dom的艺术去分析数据不是非常便宜嘛,恰好有个劳务端的jquery库cheerio。

Private

卿还是可使私人关键字展开访问控制。
Swift团队就听取了社群的汇报意见,因此,私人关键字之义现在与众多旁编程语言相似。声明也私家的实业只能以那个宣称的克外于访。

import UIKit

class NotesViewController: UIViewController {

    private var dataSource = [String]()

}

extension NotesViewController: UITableViewDataSource {

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataSource.count
    }

    ...

}

Paste_Image.png

  页面抓到手了,数据为分析下了,那便非常简单了,你可以挑选存入数据库或者写副文件保留。接下来就是起落实者的功能模块。

filePrivate

Swift
3引入了fileprivate关键字来替换原来的private关键字。您可以试试着将dataSource属性的造访权限标记为fileprivate。

import UIKit

class NotesViewController: UIViewController {

    fileprivate var dataSource = [String]()

}

extension NotesViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataSource.count
    }

    ...

}

顾名思义,fileprivate着重字用对实体的顾权限于它们声明的源文件。我们得以经过以NotesViewController仿佛的扩充名活动至独的公文来说明就或多或少。这导致我们事先遇到的错。

Paste_Image.png

程序入口

  开始布置以及初始花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);

这样改的便宜

privatefilePrivate恰好开头容许会见令人困惑,但是private具再清晰、更直观的语意。private的本来面目实现而多开发人员,特别是来源于其它编程语言的开发人员感到困惑。通过以private重命名为fileprivate,不再这样。该名清楚地代表一个实体对于特定(源)文件是私家的,而现底private暨另的编程语言里之private发平等的语意,更加鲜明。

不懂就药问

请求模块

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

数说明

  抓取数据以后,我们得举行的哪怕是调用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

总结

  这里完成的凡极核心的爬虫功能,代码请圈net_grab

发表评论

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

网站地图xml地图