首先在笑话分类中看到个爆笑男女,呵呵,先拿它小试一下,看看是否有效果。
首先编写一个main方法,内容如下:
首先构建一个爬虫,字符集是GBK,然后建立一个Watcher,Watcher用于在抓取的内容中,进行数据过滤。
如果过滤到内容呢,就执行PrintJokejiProcessor处理器进行处理。
OK主程序就写完了,上面有个类PrintJokejiProcessor也是需要自己写的,内容如下:
publicclassPrintJokejiProcessorimplementsProcessor{publicvoidprocess(HtmlNodenode){FastNameFilter
运行之,运行结果如下:
胖子是可爱滴,胖子更是的幽默滴尽情的笑话我,别骂我2B就行了这节奏,不糗死也得气疯掉太损鸟,不挨揍,也得挨骂爆笑的“二”哥爆笑的妹子们,哥有点怕你们了哈哈,逗的妹子很生气奇葩情侣,雷你到恍惚极品囧事,谁看谁爆笑爆笑的二货们刚刚过完了年幽默乐人的囧男女二货的情人节笑话段子一群爆笑又疯狂的游戏迷结婚典礼的笑场囧事一些非夷所思的搞笑糗事你这么二,不怕别人笑话么他们来自淫民大学内涵系搞笑的二货情侣屌丝爆笑,这辈子别想有女友脸都绿了,憋到内伤啊!爆笑,一帮傻傻又可爱的二货从上面的的列表看,确实已经正确抓取的到数据,小试成功。
先先Main方法
publicclassPrintJokejiCategoryProcessorimplementsProcessor{publicvoidprocess(HtmlNodenode){System.out.println(node.getContent());}}下面是运行结果:
这里就简单的处理一下,把上面的两个类小改一下:
JokejiTest类的main方法修改成静态方法processUrl,然后把下面的处理的URL变成参数传入
publicclassJokejiTest{publicstaticvoidprocessUrl(Stringurl){Spiderspider=newSpiderImpl("GBK");Watcherwatcher=newWatcherImpl();watcher.addProcessor(newPrintJokejiProcessor());QuickNameFilter
下面是调整之后的运行结果:
呵呵,还没有呢,因为你会发现有的分类下是有分页的,现在只是打出了第一页的内容。
接下来呢,为了避免有人去直接抓取人家的网页,我会贴局部代码,但是不会贴完整的代码了。当然,你能根据局部代码,整出完整的,那说明你聪明过人,偶也没有办法了。
其实,一个页面里,可以添加多个Watcher。
比如说,在笑话列表页面,再增加一下Watcher类似下面这样:
WatchernextPage=newWatcherImpl();QuickNameFilter
具体的笑话抓取,代码片断不能贴了,只说原理。
访问一个页面,很简单的就可以找到内容的节点,并抓取内容出来。
值得注意的是,如果要处理的网站有防爬虫机制,这样子很快会触发对方反应的。这里假设没有,仅讨论如何增加多线程处理模式。
要把单机的TinySpider变成分布式的,首先要解决的一个问题就是UrlRepository的问题,UrlRepository是避免URL被重复处理的机制,保存有所有已经处理过的URL列表。那可以用各种方式来写这个URL仓库,可以用数据库,可以用缓冲,或者其它复杂的手段来现。
接下来就如何进行分布式抓取了:
先来开发个工人:
publicclassWorkerPageextendsAbstractWorker{privatestaticfinallongserialVersionUID=5873591269002335547L;publicWorkerPage()throwsRemoteException{super("page");}publicWarehousedoWork(Workwork)throwsRemoteException{List
然后要实现一个任务分解器:
publicclassUrlSplitterimplementsWorkSplitter{privatestaticfinallongserialVersionUID=551260312611646323L;publicList 接下来就是构建主任务中心了: publicstaticvoidmain(String[]args)throwsIOException,ClassNotFoundException,InterruptedException{JobCenterjobCenter=newJobCenterLocal();JobCentercenter=newJobCenterRemote();for(inti=0;i<5;i++){center.registerWorker(newWorkerPage());}ForemanpageForeman=newForemanSelectAllWorker("page",newPageSplitter());center.registerForeman(pageForeman);}当然也可以在很多台计算机上都增加工人进来: publicstaticvoidmain(String[]args)throwsIOException,ClassNotFoundException,InterruptedException{JobCenterjobCenter=newJobCenterRemote();JobCentercenter=newJobCenterRemote();for(inti=0;i<5;i++){center.registerWorker(newWorkerPage());}}注意,上面的代码不同之处,在于一个是JobCenterLocal和JobCenterRemote,Local相当于服务器,Remote相当于客户端,因此,只能有一个Local,可以有多个Remote。上面把分布式的工作做好准备了,接下来进行分布式调用: 还是修改PrintJokejiProcessor 如此,就可以通过N台机器来共同完成页面抓取了。 上面的类名,方法名,变量名都是随便取的,重构之。一个完整的网站内容抓取就算完工了。最后统计了一下源代码,不到200行。import语句比真正干活的代码还多,真正干活的在方法中的语句也就100行左右。