一个简单网络爬虫示例
来源:互联网 发布:零速争霸奥迪双钻淘宝 编辑:程序博客网 时间:2024/05/02 23:36
在学生时期,可能听到网络爬虫这个词会觉得很高大上,但是它的简单实现可能学生都不难懂。网络爬虫应用,就是把整个互联网真的就当做一张网,像蜘蛛网那样,应用就像一个虫子,在网上面按照一定的规则爬动。现在互联网应用最广的就是http(s)协议了,本文例子就是基于使用http(s)协议的,只作为示例,不涉及复杂的算法(实际上是最重要的)。
设计思路:
程序入口从一个或多个url开始,通过http(s)获取url的内容,对获取到内容处理,获取内容中需要爬取的信息,获取到内容中的url链接,再重复以上步骤。
不多说,详情看代码已经注释:
/** * 功能概要:主程序 * * @author hwz */public class MainApp { private Integer corePoolSize = 10; private Integer maxPoolSize = 20; private ThreadPoolExecutor executor; /** 工作队列 */ private SpiderQueue workQueue; public void start(String url) throws Exception { //初始化线程池 LinkedBlockingDeque<Runnable> executorQueue = new LinkedBlockingDeque<Runnable>(maxPoolSize); executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, 60L, TimeUnit.SECONDS, executorQueue); workQueue = new SpiderQueue(1024); SpiderUrl spiderUrl = new SpiderUrl(url, 0); try { workQueue.add(spiderUrl); } catch (Exception e) { System.out.println("insert url into workQueue error,url=" + url); e.printStackTrace(); } //提交第一个执行任务 executor.submit(new SimpleSpider(workQueue, "thread-" + "main")); int i=0; int idle = 0; while(true) { //判断是否增加更多线程执行任务 if (workQueue.size() > 20 && executor.getActiveCount() < maxPoolSize) { idle = 0; System.out.println("submit new thread,workQueue.size=" + workQueue.size() + ",executorQueue.activeCount=" + executor.getActiveCount() + ",i=" + i); executor.submit(new SimpleSpider(workQueue, "thread-" + i++)); Thread.sleep(500); } else if (workQueue.size() == 0){ idle++; System.out.println("main method, idle times=" + idle); //主线程空闲20次,结束运行 if (idle > 20) { System.out.println("main method, idle times=" + idle + ",end!"); break; } Thread.sleep(1000); } else { Thread.sleep(2000); } } System.out.println("End!,workQueue.size=" + workQueue.size() + ",executorQueue.activeCount=" + executor.getActiveCount() + ",executorQueue.CompletedTaskCount" + executor.getCompletedTaskCount() + ",i=" + i); workQueue.printAll(); executor.shutdown(); System.exit(0); } public static void main(String[] args) throws Exception { MainApp app = new MainApp(); app.start("http://www.csdn.net/"); }}
/** * * 功能概要:自定义爬虫工作同步队列,使用ArrayList实现 * * @author hwz */public class SpiderQueue { /** 存储器 */ private List<SpiderUrl> queue; public SpiderQueue(int size) { queue = new ArrayList<SpiderUrl>(size); } public synchronized void add(SpiderUrl spiderUrl) { queue.add(spiderUrl); } public synchronized SpiderUrl poll() { if (queue.isEmpty()) { return null; } //控制台打印结果,方便查看 SpiderUrl spiderUrl = queue.remove(0); System.out.println("SpiderQueue,poll,SpiderUrl=" + spiderUrl.toString() + ",remain size=" + queue.size()); return spiderUrl; } public synchronized SpiderUrl peek() { if (queue.isEmpty()) { return null; } return queue.get(0); } public synchronized boolean isExsit(SpiderUrl spiderUrl) { return queue.contains(spiderUrl); } public synchronized int size() { return queue.size(); } public void printAll() { System.out.println("Enter printAll."); for (SpiderUrl spiderUrl : queue) { System.out.println(spiderUrl); } }}
/** * * 功能概要:爬虫工作的url * * @author hwz */public class SpiderUrl { /** http(s) url */ private String url; /** 该url是入口url的第几层 */ private int deep; public SpiderUrl(String url, int deep) { this.url = url; this.deep = deep; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getDeep() { return deep; } public void setDeep(int deep) { this.deep = deep; } @Override public boolean equals(Object obj) { if (!(obj instanceof SpiderUrl)) { return false; } SpiderUrl oth = (SpiderUrl) obj; return this.url.equals(oth.getUrl()); } @Override public int hashCode() { return url.hashCode(); } @Override public String toString() { return getClass().toString() + "[url:" + url + ",deep:" + deep +"]"; }}
/** * * 功能概要:爬虫工作类,主要实现类 * * @author hwz */public class SimpleSpider implements Runnable{ private String threadName; private SpiderUrl url; private SpiderQueue workQueue; public SimpleSpider(SpiderQueue workQueue, String threadName) { this.workQueue = workQueue; this.threadName = threadName; } @Override public void run() { System.out.println(threadName + " start run"); //连续空闲10次循环,结束任务 int idle = 0; while (idle < 10) { url = workQueue.poll(); if (url != null) { //url 解析 parseUrl(url); idle = 0; } else { System.out.println(threadName + " idle...,times=" + idle++); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } System.out.println(threadName + " end run..."); } /** * url解析 * @param url * @return void */ private void parseUrl(SpiderUrl url) { if (url == null) { return; } try { int deep = url.getDeep() + 1; URL netUrl = new URL(url.getUrl()); URLConnection connection = netUrl.openConnection(); String contentType = connection.getContentType(); //获取内容 String resource = getResource(connection); //获取标题 String title = getTitle(resource); //获取链接 List<String> urls = getUrls(resource); System.out.println(threadName + ",parseUrl url=" + url + ",contentType=" + contentType + ",title=" + title + ",urls=" + urls); //控制爬取链接层数,如果获取到的url全部加入工作队列,将会是指数级增加,最后程序挂掉 if (deep < 3) { SpiderUrl newUrl; for (String u : urls) { newUrl = new SpiderUrl(u,deep); if(!workQueue.isExsit(newUrl)) { workQueue.add(newUrl); } } } } catch (IOException e) { e.printStackTrace(); } } /** * 读取http url 内容 * @param connection * @return * @return String */ private String getResource(URLConnection connection) { if (connection == null) { return null; } StringBuilder sb = new StringBuilder(); try { InputStream inputStream = connection.getInputStream(); InputStreamReader isr = new InputStreamReader(inputStream, "UTF-8"); int input; while ( (input = isr.read()) != -1) { sb.append((char)input); } } catch (IOException e) { System.out.println(threadName + ",get resource error,connection=" + connection); } return sb.toString(); } /** * 从url内容获取标题 * @param content * @return * @return String */ private String getTitle(String content) { if (content == null) { return null; } Pattern pattern = Pattern.compile("(<title>.{1,}</title>)"); Matcher matcher = pattern.matcher(content); String title = null; if (matcher.find()) { title = matcher.group(0).replaceAll("<title>", "").replaceAll("</title>", ""); } return title; } /** * 从url内容中获取存在的url链接 * @param content * @return * @return List<String> */ private List<String> getUrls(String content) { if (content == null) { return null; } Pattern pattern = Pattern.compile("(<a.{1,}?href=['\"]?[a-zA-z]+:\\/\\/[^\\s]*?[\\s>]{1})"); Matcher matcher = pattern.matcher(content); String a; String lastChar; List<String> links = new ArrayList<String>(); while (matcher.find()) { a = matcher.group(0).replaceAll("<a.{1,}?href=['\"]?", ""); a = a.trim(); lastChar = a.substring(a.length()-1); if (lastChar.equals("'") || lastChar.equals("\"") || lastChar.equals(">")) { a = a.substring(0,a.length()-1); } links.add(a); } return links; }}
该代码示例,旨在说明一个简单的爬虫,关于多线程和http的处理没有过多考虑,如存在错误,请指出。
1 0
- 一个简单网络爬虫示例
- 简单网络爬虫代码示例
- [笔记]python网络爬虫:一个简单的爬取图片并存储示例
- [笔记]python网络爬虫:一个简单的定向爬取大学排名信息示例
- 一个简单的java网络爬虫(spider)
- 一个简单的java网络爬虫(spider)
- 一个简单的宽度优先网络爬虫
- 一个简单的网络爬虫 - SharkCrawler
- 一个简单的网络爬虫程序
- python制作一个简单网络爬虫
- 网络爬虫(六):一个简单的百度贴吧小爬虫
- Tornado官方文档(四)【Queue示例-一个并发网络爬虫】
- Java简单爬虫示例
- python3 爬虫 简单示例
- Python爬虫系列之----Scrapy(四)一个简单的示例
- 搜索引擎----Java实现一个简单的网络爬虫
- 一个最简单的网络爬虫的实现
- 一个简单的网络爬虫---爬取网页中的图片
- 在字符串中查找不定数量的子串并输出
- 2016年春找软硬件合伙人共创机器人大业,不差钱只差人,请有意向者联系我!
- ASP.Net MVC开发基础学习笔记(1):走向MVC模式
- POJ 1083:Moving Tables
- Android Studio之AndroidManifest.xml(笔记)
- 一个简单网络爬虫示例
- UITableView的headerView展开缩放动画
- 编写基于dbscan的GPS数据热点区域分析(二)算法的实现
- 软件开发管理: 每日晨会(scrum)
- Eclipse调试Android工具-adb命令大全(一)
- PHPexcel导出_Thinkphp_暂无效果图(单行导出)
- ZOJ 1029:Moving Tables
- error C2660: “Gdiplus::GdiplusBase::operator new”: 函数不接受 3 个参数
- hdu 1564 Play a game 巴什博弈/棋盘博弈问题