Crawler学习:3.Crawler Design

来源:互联网 发布:java主方法有什么作用 编辑:程序博客网 时间:2024/06/05 18:55

声明:所有内容均为本人学习《自己动手写网络爬虫》心得,有任何疑问可以参考原文。



爬虫示例结构示意图


我们可以简单得把每一个url代表的网页看作一个节点,那么网络可以看成是由若干个节点及其边组成的图。

那么爬虫的过程就是要遍历这个图,搜索我们有用的信息。

遍历图的过程有很多种,最简单的为宽度遍历、深度遍历。

以宽度遍历为例,假设我们的爬虫不具有任何偏好,我们规定它的爬行路线为宽度遍历的路线。

宽度遍历首先需要一个存储队列,也就是我们的爬虫队列。

package chici.structure;import java.util.LinkedList;public class Queue {private LinkedList queue = new LinkedList();// 进队列public void enQueue(Object obj){queue.addLast(obj);}// 出队列public Object deQueue(){return queue.removeFirst();}// 判断队列是否为空public boolean isQueueEmpty(){return queue.isEmpty();}//判断队列是否包含objpublic boolean contians(Object obj) {return queue.contains(obj);}}

及爬虫队列的操作方法。

package chici.structure;import java.util.HashSet;import java.util.Set;public class LinkQueue {private static Set visitedUrl = new HashSet();private static Queue unvisitedUrl = new Queue();// 获得URL队列public static Queue getUnVisitedUrl(){return unvisitedUrl;}// 添加到访问过的URL队列public static void addVisitedUrl(String url){visitedUrl.add(url);}//移除访问过的URLpublic static void removeVisitedUrl(String url) {visitedUrl.remove(url);}//未访问的URL 出队列public static Object unVisitedUrlDeQueue() {return unvisitedUrl.deQueue();}// 保证每个URL 只被访问一次public static void addUnvisitedUrl(String url) {if (url != null && !url.trim().equals("")&& !visitedUrl.contains(url)&& !unvisitedUrl.contians(url) )unvisitedUrl.enQueue(url);}//获得已经访问的URL 数目public static int getVisitedUrlNum() {return visitedUrl.size();}//判断未访问的URL 队列中是否为空public static boolean unVisitedUrlsEmpty() {return unvisitedUrl.isQueueEmpty();} }

除此之外,我们以url作为搜索索引。

当然我们通过url获得的是整个网页内容,我们需要一个HTML提取工具(HtmlPaserTool)从网页中提取url。

package chici.util;import java.util.HashSet;import java.util.Set;import org.htmlparser.Node;import org.htmlparser.NodeFilter;import org.htmlparser.Parser;import org.htmlparser.filters.NodeClassFilter;import org.htmlparser.filters.OrFilter;import org.htmlparser.filters.TagNameFilter;import org.htmlparser.tags.LinkTag;import org.htmlparser.util.NodeList;import org.htmlparser.util.ParserException;public class HtmlParserTool {// 获取一个网站上的链接,filter 用来过滤链接public interface LinkFilter {public boolean accept(String url);}public static Set<String> extracLinks(String url, LinkFilter filter) {Set<String> links = new HashSet<String>();try {Parser parser = new Parser(url);parser.setEncoding("UTF-8");NodeFilter frameFilter = new TagNameFilter("A");// OrFilter 来设置过滤<a> 标签和<frame> 标签OrFilter linkFilter = new OrFilter(new NodeClassFilter(LinkTag.class), frameFilter);// 得到所有经过过滤的标签NodeList list = parser.extractAllNodesThatMatch( linkFilter );for (int i = 0; i < list.size(); i++) {Node tag = (Node) list.elementAt(i);if (tag instanceof LinkTag){LinkTag link = (LinkTag) tag;String linkUrl = link.getLink();// URL//if (filter.accept(linkUrl))links.add(linkUrl);} }} catch (ParserException e) {e.printStackTrace();}return links;}}

之后就是进行宽度遍历,方法在此就不赘述了。见代码吧。

package chici.util;import java.util.Set;import chici.structure.LinkQueue;import chici.util.HtmlParserTool.LinkFilter;public class ChiciBug {/*** 使用种子初始化URL 队列* @return* @param seeds 种子URL*/private void initCrawlerWithSeeds(String[] seeds){for( int i=0; i<seeds.length; i++ )LinkQueue.addUnvisitedUrl(seeds[i]);}/*** 抓取过程* @return* @param seeds*/public void crawling(String[] seeds){ //定义过滤器,提取以http://www.baidu.com 开头的链接LinkFilter filter = new LinkFilter(){public boolean accept(String url) {if(url.startsWith("http://www.baidu.com"))return true;elsereturn false;}};//初始化URL 队列initCrawlerWithSeeds(seeds);//循环条件:待抓取的链接不空且抓取的网页不多于1000while( !LinkQueue.unVisitedUrlsEmpty()&& LinkQueue.getVisitedUrlNum() <= 1000 ){//队头URL 出队列String visitUrl=(String)LinkQueue.unVisitedUrlDeQueue();if(visitUrl==null) continue;DownloadFile downLoader=new DownloadFile();//下载网页downLoader.downloadFile(visitUrl);//该URL 放入已访问的URL 中LinkQueue.addVisitedUrl(visitUrl);//提取出下载网页中的URLSet<String> links=HtmlParserTool.extracLinks(visitUrl,filter);//新的未访问的URL 入队for(String link:links){LinkQueue.addUnvisitedUrl(link);}}}//main 方法入口public static void main(String[]args){ChiciBug chici = new ChiciBug();chici.crawling(new String[]{"http://www.baidu.com"});System.out.println("Crawling over.");}}

我们的爬虫只分析出url,并download整个网页。之后我们遍可以进一步筛选我们需要的信息。


0 0