Crawler学习:3.Crawler Design
2013-12-29 23:50
204 查看
声明:所有内容均为本人学习《自己动手写网络爬虫》心得,有任何疑问可以参考原文。
爬虫示例结构示意图
我们可以简单得把每一个url代表的网页看作一个节点,那么网络可以看成是由若干个节点及其边组成的图。
那么爬虫的过程就是要遍历这个图,搜索我们有用的信息。
遍历图的过程有很多种,最简单的为宽度遍历、深度遍历。
以宽度遍历为例,假设我们的爬虫不具有任何偏好,我们规定它的爬行路线为宽度遍历的路线。
宽度遍历首先需要一个存储队列,也就是我们的爬虫队列。
及爬虫队列的操作方法。
除此之外,我们以url作为搜索索引。
当然我们通过url获得的是整个网页内容,我们需要一个HTML提取工具(HtmlPaserTool)从网页中提取url。
之后就是进行宽度遍历,方法在此就不赘述了。见代码吧。
我们的爬虫只分析出url,并download整个网页。之后我们遍可以进一步筛选我们需要的信息。
爬虫示例结构示意图
我们可以简单得把每一个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(); } //判断队列是否包含obj public 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); } //移除访问过的URL public 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; else return false; } }; //初始化URL 队列 initCrawlerWithSeeds(seeds); //循环条件:待抓取的链接不空且抓取的网页不多于1000 while( !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); //提取出下载网页中的URL Set<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整个网页。之后我们遍可以进一步筛选我们需要的信息。
相关文章推荐
- spring的jar包maven地址,统一下载很方便
- python IDE 集合
- java模拟双色球彩票程序
- OceanBase能在Mac OS上编译吗?
- 2013蓝桥杯C/C++程序设计本科A组
- 03.WebView演练-iOS开发Demo(示例程序)源代码
- Apache -- Virtual Hosts
- Apache -- Virtual Hosts
- Apache -- Virtual Hosts
- 无意中见到一个不错的图标网站
- 2013年12月29日
- GoldenGate【OGG-01161】OGG-01161 Replicat Abends With Incompatible Record Error
- Android开发环境(Windows)
- constraints的用法总结
- 使用Strust2框架写HelloWorld
- FP-Tree算法
- Clouda聊天室实践
- 菩提本无树,明镜亦非台,本来无一物,何处惹尘埃
- 阅读优秀的代码是提高个人能力的捷径
- FP Growth算法