1. 知乎爬虫之2:爬虫流程设计

    本文由博主原创,转载请注明出处 说到爬虫,其实写起来很简单,爬虫无非就是将自己想要的内容在页面上抽离出来,并且存储。这个过程在今天已经变得非常轻松,在Java下有Jsoup,Python下有BS4,还有通吃的正则等等,然而真正难的却是在于伪造请求,截获分析请求参数,获取正确的页面. 首先来说,一个能混得过去的爬虫,应该有一个优秀的流程,在明确自己的目标后,应该立马去设计爬虫工作流程,而不是去无脑的Coding。 那么今天咱们就先研究下咱们这个爬虫的目标和流程。 首先咱们是要获取知乎页面上的个人信息,关注和被关注信息,首先咱们会遇到第一个问题就是登陆,咱们这里暂且不讲, 其次咱们就是要给定一个初始化url,然后进行followers的和followees的获取,然后循环爬起来,那么其中一定会遇到数据重复和人物关系建立的问题。 1.过滤重复数据 这个相对而言比较简单,有几种常规方法: 1. 数据库设置主键,锁定人物ID 2. 存入数据时查询数据库数据 3. 使用缓存队列,在缓存中查找数据判断 首先来说第一种,数据库设置主键,锁定人物ID,这个方法可以使数据永远不重复,但是也会造成批量插入的时候造成出错 第二种方法,存入数据时查询数据库数据,可行,但是多次访问数据库,造成效率低下 第三种方法,使用缓存队列,在缓存中查找数据判断,这种方法很好,而且速度相对较快,但是缓存太多容易出现OOM问题

    2016/11/23 Java

  2. 知乎爬虫之1:开篇序言

    本文由博主原创,转载请注明出处

    2016/11/23 Java

  3. 百度贴吧爬虫数据展示

    百度贴吧爬虫数据展示 数据来源:百度贴吧爬虫 and AutoEcharsAPI/By Accelerator、

    2016/10/31 Java

  4. 2016年11月12号聚会

    2016年11月12号聚会(吾爱Python后花园)

    2016/10/08 其它

  5. Vue.js源码分析-- eventsAPI

    这次我看的是vue源码里的eventsAPI部分,包括$emit/$broadcast/$dispatch等。 eventsAPI源码位置:src/instance/api/events.js 私有函数 modifyListenerCount var hookRE = /^hook:/ function modifyListenerCount (vm, event, count) { var parent = vm.$parent // hooks do not get broadcasted so no need // to do bookkeeping for them if (!parent || !count || hookRE.test(event)) return while (parent) { parent._eventsCount[event] = (parent._eventsCount[event] || 0) + count parent = parent.$parent } } 在events.js里边多次调用到该函数,用于向上遍历父组件,更新事件计数器。 <li>组件的_events属性,记录着每个event绑定的回调函数(数组),比如_events[event] = [func1, func2, …]. <li>组件的_eventsCount属性,记录着自己以及子组件对每个event绑定的回调函数的总数目。每当子组件对event事件绑定了n个回调,那父组件(一直向上遍历到根)的_eventsCount[event]会+n。目前发现,_eventsCount在$broadcast会使用到。 Vue.prototype.$on Vue.prototype.$on = function (event, fn) { (this._events[event] || (this._events[event] = [])) .push(fn) modifyListenerCount(this, event, 1) return this } 基础函数,事件监听绑定。组件将回调函数fn保存在_events[event]中,对同一event可以绑定多个回调函数,同时,通过modifyListenerCount更新所有父组件的_eventsCount[event]。 Vue.prototype.$once Vue.prototype.$once = function (event, fn) { var self = this function on () { self.$off(event, on) fn.apply(this, arguments) } on.fn = fn this.$on(event, on) return this } $once:当event事件发生时,fn只会被调用一次,调用完成后通过$off解除绑定。 Vue.prototype.$off Vue.prototype.$off = function (event, fn) { var cbs // all if (!arguments.length) { if (this.$parent) { for (event in this._events) { cbs = this._events[event] if (cbs) { modifyListenerCount(this, event, -cbs.length) } } } this._events = {} return this } // specific event cbs = this._events[event] if (!cbs) { return this } if (arguments.length === 1) { modifyListenerCount(this, event, -cbs.length) this._events[event] = null return this } // specific handler var cb var i = cbs.length while (i--) { cb = cbs[i] if (cb === fn || cb.fn === fn) { modifyListenerCount(this, event, -1) cbs.splice(i, 1) break } } return this } $off:解除事件绑定,源码可以看出它的三个调用方式: vm.$off() 不带参数:将删除组件所有绑定的事件(this._events = {}),在此之前,会遍历更新父组件的计数器。 vm.$off(event) 只带参数event:将删除组件对event绑定的所有事件,同样会遍历更新父组件的计数器。 vm.$off(event, fn) 带齐参数event和fn:将删除组件对event事件绑定的fn回调,同样会遍历更新父组件的计数器。

    2016/10/07 Vue

  6. 使用Java原生代理实现注入

    本文由博主原创,转载请注明出处 完整源码下载地址 https://github.com/MatrixSeven/JavaAOP 上一篇,咱们说了.使用Java原生代理实现AOP的简单例子,然么就不得不说一下Annotation这个东西了.注解(Annotation)是什么.吓得小柒君赶紧百度下: 注解基础知识点 定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。 作用分类: 编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】 代码分析:通过代码里标识的元数据对代码进行分析【使用反射】 编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】

    2015/12/09 Java设计模式

  7. 使用Java原生代理实现AOP

    本文由博主柒。原创,转载请注明出处 完整源码下载地址 https://github.com/MatrixSeven/JavaAOP 一说到AOP,大家一定会想到Spring,因为这东西实在是太强大了.但是大家一定要清楚,AOP是一只编程思想,而Spring仅仅是AOP的一种实现罢了. 首先百度下: 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。 如果你对AOP还没有了解请左移百度百科:http://baike.baidu.com/search/word?word=AOP查看. 今天呢,咱们就一起用Java原生代理实现简单的AOP功能. 首先,你得需要了解基本的反射知识,否则可能会感到困惑. 不罗嗦了,直接开始撸码 首先,咱们先写一个简单的接口.名字叫AnimalInterface,用来声明规范动物的一些基本方法. 这些方法包括 设置名字,获取名字,叫声,属性(原谅我没文化,其实就是获得是陆栖还是水栖或者水陆两栖) package proxy.imp; public interface AnimalInterface { //设置名字 void setName(String name); //获取名字 String getName(); //叫声 void say(); //获取栖性 void getProperty(); } 然后咱们实现这个接口,创建一个名叫小黑的Dog package proxy; import proxy.imp.AnimalInterface; public class DogImp implements AnimalInterface { private String name = "小黑"; public DogImp() { } @Override public void setName(String name) { this.name = name; } @Override public String getName() { return this.name; } @Override public void say() { System.out.println("小狗:汪汪汪汪....."); } @Override public void getProperty() { System.out.println("小狗是陆地动物,但是会游泳哦"); } } 大家一定迫不及待了,怎么实现类似AOP的功能呢…. 咱们先创建一个名为AOPHandle的类,让其实现InvocationHandler接口, 不能使用invoke时使用proxy作为反射参数时,因为代理对象的接口,不同于对象, 这种代理机制是面向接口,而不是面向类的,如果使用proxy,会造成无限递归.然后就是栈溢出,但是依旧能反射成功一次, 这说明代理对象和对象的代理是不一样的,但是咱们可以通过proxy参数的proxy.getClass()获得class对象,然后获得被代理 类的方法和参数,这也为注解注入,特定方法注入,属性注入提供了一种实现途径吧,关于这个,咱们后面再说.. package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class AOPHandle implements InvocationHandler{ //保存对象 private Object o; public AOPHandle(Object o) { this.o=o; } /** * 这个方法会自动调用,Java动态代理机制 * 会传入下面是个参数 * @param Object proxy 代理对象的接口,不同于对象 * @param Method method 被调用方法 * @param Object[] args 方法参数 * 不能使用invoke时使用proxy作为反射参数时,因为代理对象的接口,不同于对象 * 这种代理机制是面向接口,而不是面向类的 **/ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //方法返回值 Object ret=null; //打印方法名称 System.err.println("执行方法:"+method.getName()+"n参数类型为:"); //打印参数 for(Class type:method.getParameterTypes()) System.err.println(type.getName()); //打印返回类型 System.err.println("返回数据类型:"+method.getReturnType().getName()); //反射调用方法 ret=method.invoke(o, args); //声明结束 System.err.println("方法执行结束"); //返回反射调用方法的返回值 return ret; } } 动态代理已经搞定..然后就是咱们的AnimalFactory了..咱们继续 package proxy; import java.lang.reflect.Proxy; public class AnimalFactory { /*** * 获取对象方法 * @param obj * @return */ private static Object getAnimalBase(Object obj){ //获取代理对象 return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new AOPHandle(obj)); } /*** * 获取对象方法 * @param obj * @return */ @SuppressWarnings("unchecked") public static T getAnimal(Object obj){ return (T) getAnimalBase(obj); } /*** * 获取对象方法 * @param className * @return */ @SuppressWarnings("unchecked") public static T getAnimal(String className){ Object obj=null; try { obj= getAnimalBase(Class.forName(className).newInstance()); } catch (Exception e) { e.printStackTrace(); } return (T)obj; } /*** * 获取对象方法 * @param clz * @return */ @SuppressWarnings("unchecked") public static T getAnimal(Class clz){ Object obj=null; try { obj= getAnimalBase(clz.newInstance()); } catch (Exception e) { e.printStackTrace(); } return (T)obj; } } 终于到最后了…还差什么呢,大家来这里看看效果吧… 哈哈…小二,上个菜..哦~不对,是个测试类..哈哈//// package proxy; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.BlockJUnit4ClassRunner; import proxy.AnimalFactory; import proxy.imp.AnimalInterface; @RunWith(BlockJUnit4ClassRunner.class) public class AOPTest { @Test public void Test1() { AnimalInterface dog=AnimalFactory.getAnimal(DogImp.class); dog.say(); System.out.println("我的名字是"+dog.getName()); dog.setName("二狗子"); System.out.println("我的名字是"+dog.getName()); } } 对,咱们的效果已经看到了.. ,咦,你会说没图没真相??? 好,那就上图… 图片在sae上已经丢失,请大家脑补 啥?什么,,到了最后说,,这又卵用,这不是坑爹么?就捕获一个这个玩意,什么用啊… 什么AOP,我怎么一点AOP的影子都没有看到,怎么切入自定义方法,就一个syso输入,往这忽悠观众来了?….. 好吧,那咱们继续…看看如何实现注入自定义方法… 首先增加一个接口,咱们就称为AOP注入接口吧.取名AOPMethod哈 创建after和before方法,接收Object proxy, Method method, Object[] args参数 这样就能做更多的事情叻…比如执行方法前,记录类状态,写入log.监控xx变量,,, 开启你的脑洞吧.

    2015/12/08 Java设计模式

  8. 有趣的JavaScript。简单数学的应用

    这个是2014年十一月份de在qq空间发布的。。。 搬到这里来。 2015年10月19日 发布在www.zhaoguilin.com在,最后迁移至此。 因为@R 现在每当用到数学就想到曾经的。。 怀念完了,那就说说吧,首先这是我在google上面发现的一个写法。看了代码后觉得挺神奇的,就想了下,瞬间觉得数学屌爆了~

    2015/10/19 JavaScript