网络爬虫简单功能工具类

package com.leo.web.parser.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.nodes.TagNode;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
/**
 * @date 2016年9月2日 08:43:22
 * @author 刘宗洋
 * @email 595324626@qq.com
 *
 */
public class FileUtil {
	/**
	 * 文档去重
	 * 
	 * @param fileName
	 * @return
	 */
	public static List<String> readFile(String fileName) {
		File file = new File(fileName);
		BufferedReader reader = null;
		HashSet<String> sets = new HashSet<String>();
		try {
			reader = new BufferedReader(new FileReader(file));
			String tempString = null;
			// 一次读入一行,直到读入null为文件结束
			while ((tempString = reader.readLine()) != null) {
				sets.add(tempString);
			}
			reader.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e1) {
				}
			}
		}
		List<String> lines = new ArrayList<String>();
		for (String line : sets) {
			lines.add(line);
		}
		return lines;
	}

	/**
	 * 一次性读取文件所有内容
	 * 
	 * @param fileName
	 * @return
	 */
	public static String readToString(String fileRealPath) {
		String encoding = "UTF-8";
		File file = new File(fileRealPath);
		Long filelength = file.length();
		byte[] filecontent = new byte[filelength.intValue()];
		try {
			FileInputStream in = new FileInputStream(file);
			in.read(filecontent);
			in.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			return new String(filecontent, encoding);
		} catch (UnsupportedEncodingException e) {
			System.err.println("The OS does not support " + encoding);
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 导出文件
	 * 
	 * @param content
	 *            字符串
	 * @param filePath
	 *            保存路径
	 */
	public static void output(String content, String filePath) {
		FileOutputStream fop = null;
		File file;
		try {
			file = new File(filePath);
			fop = new FileOutputStream(file);

			// if file doesnt exists, then create it
			if (!file.exists()) {
				file.mkdirs();
				file.createNewFile();
			}

			// get the content in bytes
			byte[] contentInBytes = content.getBytes();

			fop.write(contentInBytes);
			fop.flush();
			fop.close();

		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (fop != null) {
					fop.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 从外网下载文件
	 * 
	 * @param httpUrl
	 *            字符串
	 * @param saveFile
	 *            保存路径
	 */
	public static boolean httpDownload(String saveFile, String httpUrl) {
		// 下载网络文件
		// int bytesum = 0;
		int byteread = 0;

		URL url = null;
		try {
			url = new URL(httpUrl);
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
			return false;
		}

		File f = new File(saveFile);
		if (f.exists()) {
			return false;
		}
		String path = saveFile.substring(0, saveFile.lastIndexOf("/") + 1);
		FileUtil.createFile(path);
		try {
			URLConnection conn = url.openConnection();
			InputStream inStream = conn.getInputStream();
			FileOutputStream fs = new FileOutputStream(saveFile);

			byte[] buffer = new byte[1204];
			while ((byteread = inStream.read(buffer)) != -1) {
				// bytesum += byteread;
				fs.write(buffer, 0, byteread);
			}
			fs.close();
			return true;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 获取网页源代码
	 * 
	 * @param pageUrl
	 *            网页url
	 * @param encoding
	 *            编码方式
	 * @return 源码
	 */
	public static String getPageSource(String pageUrl) {
		StringBuffer sb = new StringBuffer();
		try {
			// 构建一URL对象
			URL url = new URL(pageUrl);
			// 使用openStream得到一输入流并由此构造一个BufferedReader对象
			BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
			String line;
			// 读取www资源
			while ((line = in.readLine()) != null) {
				sb.append(line);
				sb.append("\n");
			}
			in.close();
		} catch (Exception ex) {
			System.err.println(ex);
		}
		return sb.toString().replace("\n", "");
	}

	/**
	 * 调用htmlparser方法返回网页源码
	 * 
	 * @return
	 */
	public static String getParserHtml(String url) {
		String str = "";
		try {
			Parser parser = new Parser();
			URL url1 = new URL(url);
			URLConnection conn = url1.openConnection();
			conn.setConnectTimeout(500);
			parser.setEncoding("UTF-8");
			parser.setConnection(conn);
			NodeList nodeList = parser.parse(null);
			str = nodeList.toHtml();
		} catch (Exception e1) {
			// System.out.println("连接打不开!");
		}
		return str;
	}

	/**
	 * 创建文件夹
	 * 
	 * @param path
	 */
	public static void createFile(String path) {
		File file = new File(path);
		if (!file.exists()) {
			file.mkdirs();
		}
	}

	/**
	 * 从URL网址获取源并把所有匹配到的a标签的链接保存到txt文件
	 * 
	 * @param url
	 *            网址
	 * @param fileSavePath
	 *            txt文件保存地址
	 * @param attributeName
	 *            a标签属性名
	 * @param attributeValue
	 *            a标签属性值
	 * @return 如果返回0 :没有匹配到数据
	 */
	public static Integer exportLinkToTXTFromHTTP(String url, String fileSavePath, String attributeName,
			String attributeValue) {
		try {
			String inputHTML = getParserHtml(url);
			List<LinkTag> tags = (List<LinkTag>) parseTags(inputHTML, LinkTag.class, attributeName, attributeValue);
			if (tags.size() > 0) {
				StringBuffer sb = new StringBuffer();
				for (LinkTag linkTag : tags) {
					sb.append(linkTag.getLink() + "\r\n");
				}
				String str = sb.toString();
				FileUtil.output(str.substring(0, str.length() - 2), fileSavePath);
				System.out.println("获取完毕!共" + tags.size() + "条");
				return tags.size();
			} else {
				return 0;
			}
		} catch (Exception e) {
			// TODO: handle exception
			return 0;
		}
	}

	/**
	 * 从本地获取源并把所有匹配到的a标签的链接保存到txt文件
	 * 
	 * @param filePath
	 *            网址
	 * @param fileSavePath
	 *            txt文件保存地址
	 * @param attributeName
	 *            a标签属性名
	 * @param attributeValue
	 *            a标签属性值
	 * @return 如果返回0 :没有匹配到数据
	 */
	public static Integer exportLinkToTXTFromLocalHost(String filePath, String fileSavePath, String attributeName,
			String attributeValue) {
		try {
			String inputHTML = FileUtil.readToString(filePath);
			List<LinkTag> tags = (List<LinkTag>) parseTags(inputHTML, LinkTag.class, attributeName, attributeValue);
			if (tags.size() > 0) {

				StringBuffer sb = new StringBuffer();
				for (LinkTag linkTag : tags) {
					sb.append(linkTag.getLink() + "\r\n");
				}
				String str = sb.toString();
				FileUtil.output(str.substring(0, str.length() - 2), fileSavePath);
				System.out.println("获取完毕!共" + tags.size() + "条");
				return tags.size();
			} else {
				return 0;
			}
		} catch (Exception e) {
			// TODO: handle exception
			return 0;
		}
	}

	/**
	 * 解析具有某类属性值的标签列表
	 * 
	 * @see 定义泛型--><T extends TagNode>
	 * @see 使用泛型-->List <T>,Class <T>
	 * @see 这里定义了一个类型必须是某种TagNode的泛型T,并且返回的List也必须是泛型T
	 * @see 而Class<T>的意思是传给tagType的是什么类型,所以返回给List<T>的就是什么类型
	 * @see 比如传进来的是org.htmlparser.tags.MetaTag.class,那么返回的就是List<MetaTag>
	 * @param inputHTML
	 *            被解析的HTML文本
	 * @param tagType
	 *            标签的类型,内部类使用故final
	 * @param attributeName
	 *            待解析的属性名,内部类使用故final
	 * @param attributeValue
	 *            待解析的属性值,内部类使用故final
	 */
	@SuppressWarnings({ "unchecked", "serial" })
	public static <T extends TagNode> List<T> parseTags(String inputHTML, final Class<T> tagType,
			final String attributeName, final String attributeValue) {
		// 创建一个HTML解析器
		Parser parser = new Parser();
		NodeList tagList = null;
		try {
			parser.setInputHTML(inputHTML);
			// 它会自动检测文件内部<meta http-equiv="Content-Type" content="text/html;
			// charset=UTF-8"/>
			// parser.setEncoding("UTF-8");
			NodeFilter nodeFilter = new NodeFilter() {
				@Override
				public boolean accept(Node node) {
					// 这里不需要if(node instanceof TagNode),因为上面已经定义了TagNode类型的泛型T
					if (node.getClass() == tagType) {
						// Node类型的实现类中只有TagNode才能getAttribute()获取属性值,所以要将之打回原形
						T t = (T) node;
						// 若传入的属性名是null,则认为是不需要查找指定属性值的标签,而是单纯的查找某类型T的标签
						// if(null == attributeName){
						// return true;
						// }
						if (null != attributeValue && attributeValue.equals(t.getAttribute(attributeName))) {
							return true;
						}
					}
					return false;
				}
			};
			tagList = parser.extractAllNodesThatMatch(nodeFilter);
		} catch (ParserException e) {
			System.out.println("解析HTML文本时发生异常:" + e.getMessage());
		}
		// 过滤重复tag
		HashSet<T> tagSets = new HashSet<T>();
		for (int i = 0; i < tagList.size(); i++) {
			T t = (T) tagList.elementAt(i); // 提取真实tag
			tagSets.add(t);
		}
		List<T> tags = new ArrayList<T>();
		for (T t : tagSets) {
			tags.add(t);
		}
		return tags;
	}

	/**
	 * 解析属性值唯一的标签
	 * 
	 * @see 和上面那个方法差不多,传给Class<T>的是什么类型,那么返回的就是什么类型
	 */
	public static <T extends TagNode> T parseTag(String inputHTML, final Class<T> tagType, final String attributeName,
			final String attributeValue) {
		List<T> tagList = parseTags(inputHTML, tagType, attributeName, attributeValue);
		if (null != tagList && tagList.size() > 0) {
			return tagList.get(0);
		} else {
			return null;
		}
	}

	/**
	 * @param url
	 * @param encoding
	 * @return
	 */
	public static String checkURL(String url, String encoding) {
		String str = "";
		try {
			Parser parser = new Parser();
			URL url1 = new URL(url);
			URLConnection conn = url1.openConnection();
			conn.setConnectTimeout(500);
			parser.setEncoding("UTF-8");
			parser.setConnection(conn);
			NodeList nodeList = parser.parse(null);
			str = nodeList.toHtml();
		} catch (Exception e1) {
			System.out.println("连接打不开!");
		}
		return str;
	}

	/**
	 * 通过正则提取字符串中的项目 返回list
	 * 
	 * @param str
	 * @param keywords
	 * @return
	 */
	public static List<String> getList(String str, String keywords) {
		HashSet<String> set = new HashSet<String>();
		Pattern pattern = Pattern.compile(keywords);
		Matcher matcher = pattern.matcher(str);
		while (matcher.find()) {
			set.add(matcher.group());
		}
		List<String> list = new ArrayList<String>();
		list.addAll(set);
		return list;
	}

	/**
	 * 复制单个文件
	 * 
	 * @param oldFile
	 *            :File
	 * @param newPath
	 *            :String 文件路径
	 */
	public static void copyFile(File oldFile, String newPath) {
		File file = new File(newPath.substring(0,newPath.length()-21));
		if(!file.exists()){
			file.mkdirs();
		}
		// Long starttime = System.currentTimeMillis();

		InputStream inStream = null;
		FileOutputStream fout = null;
		try {
			@SuppressWarnings("unused")
			int bytesum = 0;
			int byteread = 0;
			if (oldFile.exists()) { // 文件存在时
				inStream = new FileInputStream(oldFile); // 读入原文件
				fout = new FileOutputStream(newPath);
				byte[] buffer = new byte[1024];
				while ((byteread = inStream.read(buffer)) != -1) {
					bytesum += byteread; // 字节数 文件大小
					fout.write(buffer, 0, byteread);
				}
				fout.flush();
			}
		} catch (Exception e) {
			// System.out.println("复制文件【" + oldFile.getAbsolutePath() +
			// "】时出错!");
			e.printStackTrace();
		} finally {
			try {
				// 关闭输入流
				if (inStream != null) {
					inStream.close();
				}

				// 关闭输出流
				if (fout != null) {
					fout.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		// Long endtime = System.currentTimeMillis();
		// System.out.println("复制【" + oldFile.getAbsolutePath() + " 】用时【" +
		// (endtime - starttime) + "】毫秒!");
	}
	/**
	 * 删除多个文件
	 * 
	 * @param filePaths
	 *            文件路径数组
	 */
	public static void deleteFiles(String[] filePaths) {
		for (int i = 0; i < filePaths.length; i++) {
			File file = new File(filePaths[i]);
			if (file.exists()) {
				file.delete();
			}
		}
	}
	
	/**
	 * 分割list成指定的份数
	 * @param list
	 * @param count 制定分割成几份
	 * @return
	 */
	public static Map<Integer, List<String>> cutList(List<String> list,Integer count) {
		Map<Integer, List<String>> listMap = new HashMap<Integer,List<String>>();
		
		for (int i = 1; i <= count; i++) {
			Integer counter = list.size() / count;
			listMap.put(i, list.subList((i - 1) * counter, counter * i));
		}
		Integer countAdd = list.size() % count;
		if (countAdd > 0) {
			listMap.put(count+1, list.subList(list.size() - countAdd, list.size()));
		}
		return listMap;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值