网络爬虫

简介

1. 什么是网络爬虫:
网络爬虫(又被称为网也蜘蛛,网络机器人,在FOAF社区中间,更经常称为网页追逐者。)
作用
网络蜘蛛是用过网页的链接地址来寻找网页。
从网站某一个页面(通常是首页)开始,读取网页的内容,找到在网页中的其它链接地址,然后通过这些链接地址寻找下一个网页,这样一直循环下去,直到把这个网站所有的网页都抓取完为止。如果把整个互联网当成一个网站,那么网络蜘蛛就可以用这个原理把互联网上所有的网页都抓取下来。
网络爬虫的思路以及实现
解析网络类资源的方法,通过网络URL,是利用HTTPclient技术,获取网络资源类容。

// 解析网络资源类的方法
	// 用过网络URL,是利用HTTPclient技术,获取网络资源类容
	    //定义需要过滤的文件后缀
	private static String[] fiterUrls = new String[] { ".com/tv/", ".htm" };
	//定义队列(所放的是需要再次解析的URL)
	private static Queue<String> waitForCrawler = new LinkedList<String>();
	//爬取目标的总数
	private static long total = 0;
	public static void parseUrl() {
		while (waitForCrawler.size() > 0) {
			// 摘取队列的url,并摘除掉
			String url = waitForCrawler.poll();
			
			CloseableHttpClient httpClient = HttpClients.createDefault();
			// 获取一个请求
			HttpGet httpGet = new HttpGet(url);
			// 关闭响应
			CloseableHttpResponse response = null;
			try {
				response = httpClient.execute(httpGet);
				HttpEntity entity = response.getEntity();
				// System.out.println(entity.getContentType().toString());
				// System.out.println(entity.getContentType().getValue());
				/**
				 * 获取此类型的url,需要再次解析
				 */
				if ("text/html; charset=GB2312".equals(entity.getContentType().getValue())) {
					/**
					 * 获取网页内容
					 */
					String pageContent = EntityUtils.toString(entity, "utf-8");
					// System.out.println("网页内容"+pageContent);
					parsepageContent(pageContent, url);
				}

			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {

				e.printStackTrace();
			} finally {
				// 关闭资源
				if (response != null) {
					try {
						response.close();
					} catch (IOException e) {
						
						e.printStackTrace();
					}
				}
				if (httpClient != null) {
					try {
						httpClient.close();
					} catch (IOException e) {

						e.printStackTrace();
					}
				}
			}
		}

	}

通过网络爬虫框架对网进行再次解析
1.

private static void parsepageContent(String pageContent, String realDir) {
		// 节点
		Document doc = Jsoup.parse(pageContent);
		//获取节点元素
		Elements aEles = doc.select("a");
		for (Element aEle : aEles) {
			// 获取网页url
			String aHref = aEle.attr("href");
			// System.out.println(aHref);
			// 获取真实url地址
			String url = realDir + aHref;
			System.out.println(url);
			if (url == null || "".equals(url)) {
				return;
			}
			/**
			 * 1目标链接  2 需要过滤的链接 3需要迭代解析的链接
			 */
			boolean f = true;// 假设就是我们需要的目标资源
			/**
			 * 循环遍历所有url
			 */

			for (String filterUrl : fiterUrls) {
				// 如果所遍历的url与你定义不需要的文件后缀,就过滤掉
				if (url.endsWith(filterUrl)) {
					f = false;
					break;
				}
			}
			if (f && url.endsWith(".html")) {
				System.out.println("爬取了第" + (++total) + "个目标文件,url为:" + url);
			     
			} else {
			//需要再次爬取的URL
				addUrl(url);
			}

		}

	}

添加到爬虫队列,等待再次爬取

private static void addUrl(String url) {
		System.out.println(url + "被添加到爬虫队列");
		waitForCrawler.add(url);
	}

初始化方法

public static void init() {
		// String url = "https://www.qq.com/";
		//网络URL被放进队列中,默认一个被解析的网络url
		addUrl("https://www.qq.com/");
		parseUrl();
	}

main方法测试

	public static void main(String[] args) {
		// // 默认一个网页的链接地址
		// String url = "https://www.qq.com/";
		// // 解析url
		// parseUrl(url, url);
		init();
	}

网络爬虫框架所需要的jar包
HTTPclient点击下载
jsoup点击下载
log4j点击下载
引用到你的项目里面就ok了
注意此时的网络爬虫的性能是非常差的。所以进行了进一步优化
利用异步线程池进行优化
1.默人解析爬虫队列的URL(全局变量),创建能存放10个异步线程的线程池

	       public static boolean exeFlag = true;// 默认解析爬虫队列中的url
		// 创建能存放10个异步线程的线程池
		ExecutorService executorService = Executors.newFixedThreadPool(10);

2,使用异步线程池进行逻辑解析

// 使用线程中的线程池中的异步线程解析逻辑
				executorService.execute(new Runnable() {
					@Override
					public void run() {
						while (waitForCrawler.size() > 0) {
							// 摘取队列的url,并以除掉
							String url = waitForCrawler.poll();
							CloseableHttpClient httpClient = HttpClients.createDefault();
							// 获取一个请求
							HttpGet httpGet = new HttpGet(url);
							// 设置连接时间5秒,等待服务器响应数据时间10秒
							RequestConfig config = RequestConfig.custom().setConnectTimeout(5000)
									.setSocketTimeout(10000).build();

							httpGet.setConfig(config);

3,这是逻辑判断的else

	// 获取正在执行爬虫任务的线程数
				if (((ThreadPoolExecutor) executorService).getActiveCount() == 0) {
					exeFlag = false;
					break;
				}

4,为了尽可能避免意外的发生,给点一个休眠时间

	Thread.sleep(1000);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值