最近学习了一下爬虫,发现Java真的是一门强大的语言,方方面面。

1. 爬虫一

指定一个网站,通过正则表达式对服务器返回的数据进行匹配,将符合的信息保存在本地。

/**
 * 用Java实现爬虫
 * @author aa
 *
 */
public class Robot {

	public static void main(String[] args){
		URL url = null;
		URLConnection urlconn = null;
		BufferedReader br = null;
		PrintWriter pw = null;
//		正则表达式
		String regex = "https://[\\w+\\.?/?]+\\.[A-Za-z]+";
		Pattern p = Pattern.compile(regex);
		try{
			url = new URL("https://www.rndsystems.com/cn");
			urlconn = url.openConnection();
			pw = new PrintWriter(new FileWriter("F:/SiteURL.txt"), true);
			br = new BufferedReader(new InputStreamReader(
							urlconn.getInputStream()));
			String buf = null;
			while((buf = br.readLine())!=null){
				Matcher buf_m = p.matcher(buf);
				while(buf_m.find()){
					pw.println(buf_m.group());
				}
			}
			System.out.println("爬取成功");
		}catch (MalformedURLException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}finally{
			try{
				br.close();
			}catch(IOException e){
				e.printStackTrace();
			}
			pw.close();
		}
	}
}

2. 爬虫二

这个爬虫就更为复杂一些,首先我们指定一个URL,然后对爬取数据进行筛选,将数据中的URL提取出来,重复进行爬取(简单讲,这就是一个循环爬取网页中的网址的爬虫)。为了保证爬取的网站不重复且爬取网站不遗漏,我们创建两个list集合:listOfPendingURLs存放将要爬取的url、listOfTraversedURL是存放已爬取的url。(具体实现详见代码)

/**
 * Java实现爬虫二
 * @author aa
 *
 */
public class WebCrawler {

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		System.out.println("Enter a URL:");
		String url = input.nextLine();
		craweler(url);
	}

	/**
	 * 对指定的url进行爬取
	 * @param url
	 */
	private static void craweler(String url) {
		ArrayList<String> listOfPendingURLs = new ArrayList<>();
		ArrayList<String> listOfTraversedURLs = new ArrayList<>();
//		将起始的URL添加到listOfPendingURLs,然后处理其中的每一个url
		listOfPendingURLs.add(url);
		while(!listOfPendingURLs.isEmpty() && listOfTraversedURLs.size() <= 100){
//			将列表中的第一个URL去除,如果该URL没有被处理过则对其进行处理
			String urlString = listOfPendingURLs.remove(0);
			if(!listOfTraversedURLs.contains(urlString)){
				listOfTraversedURLs.add(urlString);
				System.out.println("Crawling: c"+urlString);
//				将页面中每个不存在listOfTraversedURLs中的url添加到listOfPendingURLs中
				for (String s : getSubURLs(urlString)) {
					if(!listOfTraversedURLs.contains(s))
						listOfPendingURLs.add(s);
				}
			}
		}
	}

	/**
	 * 该方法为每个给定的url返回一个url列表
	 * @param urlString
	 * @return
	 */
	private static ArrayList<String> getSubURLs(String urlString) {
		ArrayList<String> list = new ArrayList<>();
		try{
			URL url = new URL(urlString);
			Scanner input = new Scanner(url.openStream());
			int current = 0;
			while(input.hasNext()){
				String line = input.nextLine();
				current = line.indexOf("http:", current);
				while(current > 0){
					int endIndex = line.indexOf("\"", current);//假设URL以引号"结束
					if(endIndex > 0){
						list.add(line.substring(current, endIndex));//一行中可能包含多个url
						current = line.indexOf("http:", endIndex);//继续寻找下一个URL
					}else{
						current = -1; //如果该行没有发现URL,current设为-1
					}
				}
			}
		}catch(Exception e){
			System.out.println("Error"+e.getMessage());
		}
		return list;//以列表的形式返回
	}
}

给与的爬虫终止条件是爬取URL超过100条。

java 写爬虫案例 java编写爬虫_System

 3. 爬虫三

根据输入的URL,爬取其页面上的图片。

程序中使用了httpclient和commons-lang等相关包,我们使用maven进行导入。

maven依赖:

<!-- httpclient -->
         <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient</artifactId>
             <version>${httpclient.version}</version>
         </dependency>
         <!-- Apache工具组件 -->
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
             <version>${commons-lang3.version}</version>
         </dependency>
/**
 * Java实现爬虫三 功能: 从一个网址上爬取图片,然后重命名保存到本地路径中
 * 
 * @author aa
 *
 */
public class DownloadImageUtil {

	// 图片保存路径
	public static final String IMAGE_SAVE_PATH = "F:\\image\\DownloadImageUtil";
	// 获取img标签正则表达式
	public static final String IMGURL_REG = "<img.*src=(.*?)[^>]*?>";
	// 获取src路径的正则表达式
	public static final String IMGSRC_REG = "(http|https):\"?(.*?)(\"|>|\\s+)";

	public static final String[] IMAGE_TYPE_SUFFIX = new String[] { "=png", "=jpg", "=jpeg", ".png", ".jpg", "jpeg" };

	// 默认生成的图片名称从1开始递增
	public static Integer imageIndex = 1;

	public static void main(String[] args) {
		// 爬取的网页url
		String rquestURL = null;
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入一个URL地址:");
		rquestURL = sc.nextLine();
		// 通过请求url解析出相应内容
		String htmlContent = ParserContext(rquestURL);
		// 通过正则表达式匹配,取出data-src的图片链接放入到list中
		List<String> imageUrlList = getImageSrc(htmlContent);

		for (String imageUrl : imageUrlList) {
			try {
				download(imageUrl, IMAGE_SAVE_PATH);
			} catch (Exception e) {
				System.out.println(e.getMessage());
			}
		}
		System.out.println("从{" + rquestURL + "]网站,共抓取[" + (imageIndex - 1) + "]张图片");
	}

	/**
	 * 解析图片url路径,保存到对应目录下
	 * 
	 * @param imageUrl
	 * @param imageSavePath
	 * @throws IOException
	 */
	private static void download(String imageUrl, String imageSavePath) throws IOException {

		String imageType = "";
		boolean flag = false;
		for (String suffix : IMAGE_TYPE_SUFFIX) {
			if (imageUrl.lastIndexOf(suffix) > -1 || imageUrl.lastIndexOf(suffix.toUpperCase()) > -1) {
				flag = true;
				imageType = suffix.replace("=", ".");
				break;
			}
		}
		// 存在该图片类型
		if (flag) {
			String filename = String.valueOf(imageIndex) + imageType;
			download(imageUrl, filename, imageSavePath);
			imageIndex++;
		}
	}

	private static void download(String imageUrl, String filename, String imageSavePath) throws IOException {

		if (StringUtils.isEmpty(imageUrl) || StringUtils.isEmpty(filename) || StringUtils.isEmpty(imageSavePath)) {
			throw new IllegalArgumentException("方法入参不能为空");
		}

		// 如果目录不存在,就新增一个
		File dir = new File(imageSavePath);
		if (!dir.exists() && dir.isDirectory()) {
			dir.mkdir();
		}

		// 构造URL
		URL url = new URL(imageUrl);
		// 打开连接
		URLConnection urlConn = url.openConnection();
		// 设置请求超时为5s
		urlConn.setConnectTimeout(5 * 1000);
		// 输入流
		InputStream is = urlConn.getInputStream();

		// 创建缓冲区
		byte[] bs = new byte[1024];
		// 读取数据长度
		int len;
		// 输出的文件流
		OutputStream os = new FileOutputStream(dir.getPath() + "/" + filename);

		while ((len = is.read(bs)) != -1) {
			os.write(bs, 0, len);
		}
		// 资源释放
		os.close();
		is.close();
	}

	/**
	 * 通过正则表达式的匹配,获取ImageSrc的地址
	 * 
	 * @param htmlContent
	 * @return
	 */
	private static List<String> getImageSrc(String htmlContent) {

		if (htmlContent == null) {
			throw new IllegalArgumentException("html请求内容不能为空.");
		}
		List<String> listImageUrl = getImageUrl(htmlContent);

		List<String> listImageSrc = new ArrayList<>();

		for (String imageContent : listImageUrl) {
			Matcher matcher = Pattern.compile(IMGSRC_REG).matcher(imageContent);
			while (matcher.find()) {
				listImageSrc.add(matcher.group().substring(0, matcher.group().length() - 1));
			}
		}
		return listImageSrc;
	}

	/**
	 * 通过正则表达式获取ImageURL的地址
	 * 
	 * @param htmlContent
	 * @return
	 */
	private static List<String> getImageUrl(String htmlContent) {

		if (htmlContent == null) {
			throw new IllegalArgumentException("html请求内容不能为空.");
		}

		List<String> listImgUrl = new ArrayList<String>();
		Matcher matcher = Pattern.compile(IMGURL_REG).matcher(htmlContent);

		while (matcher.find()) {
			listImgUrl.add(matcher.group().replaceAll("'", ""));
		}

		return listImgUrl;
	}

	/**
	 * 读取url中的相应内容并返回
	 * 
	 * @param requestUrl
	 * @return
	 */
	private static String ParserContext(String requestUrl) {

		if (requestUrl == null) {
			throw new IllegalArgumentException("url不能为空.");
		}

		String html = null;
		// 创建httpClient对象
		CloseableHttpClient httpclient = HttpClients.createDefault();
		try {
			// 创建httpget对象
			HttpGet httpGet = new HttpGet(requestUrl);
			// 执行get请求
			CloseableHttpResponse response = httpclient.execute(httpGet);
			try {
				// 获取响应实体
				HttpEntity entity = response.getEntity();
				if (entity != null) {
					html = EntityUtils.toString(entity);
				}
			} finally {
				response.close();
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 关闭连接
			try {
				httpclient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return html;
	}
}