1. 程式人生 > >用java抓取網頁圖片

用java抓取網頁圖片

記得是這個月9號來深圳的,找了快20天的工作,結果只有那麼三四家公司打電話要我去面試,真的不知道什麼原因啊。是我投簡歷投簡歷投少了麼?還是這個季節就是招聘冷季節?真的不清楚。前天去一家創業公司面試,公司感覺還好,整體還算滿意,很幸運的被面試上了。談的工資也是我能接受的,就答應了去上班。今天是第一天去上班,晚上回到住處就在思索著寫點什麼東西來呢?這個月就要結束了。時間真的過得很快,不過還好,在找工作過程中,自己看了一些書,寫了兩個小程式。就把前兩天在弄得用java抓取網頁資料的程式記錄下來。以供後面參考。

一般抓取網頁資料都是用PHP,Python,Ruby等指令碼語言,其實像Java,C++也是可以的,只是可能操作的時候沒那麼方便。抓取網頁原理都一樣,通過正則表示式把所關注的網頁資料從網頁裡面提取出來,然後在進行操作(寫入檔案或者資料庫等)。java中操作正則表示式主要用到java.util.regex這個包。比如我們要把某個網頁中的<title>XXX</title>中的XXX提取出來,這個時候怎麼做呢?

/**
	 * 獲取網頁title
	 * 
	 * @param pageStr
	 * @return
	 */
	public static String getPageTitle(String pageStr) {
		String titleRegStr = "<title>(.*)</title>";
		Pattern pattern = Pattern
				.compile(titleRegStr, Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher(pageStr);
		String pageTitle = "";
		if (matcher.find(0)) {
			pageTitle = matcher.group(1);
		}
		return pageTitle;
	}

通過上面程式碼就可提取出來,注意傳入引數是整個要提取的網頁字串。返回的就是網頁title。

網頁中圖片連結一般都是這樣寫的: <img src="XXX"  onClicked="XXX" /> 一般網頁的連線都是類似這樣<a href="XXX"   target="_blank"/>。抓取src後面的值和href後面的值原理是一樣的。

/**
	 * 得到網頁中圖片的地址
	 */
	public static List<String> getImgStr(String htmlStr, String url) {
		StringBuffer imgBuffer = new StringBuffer();
		Pattern p_image;
		Matcher m_image;
		List<String> pics = new ArrayList<String>();
		String cache_file_name = url.substring(url.lastIndexOf("/") +1);
		File file = new File(CACHE_PATH+"/"+cache_file_name);
		if (file.exists()) {
			try {
				FileInputStream fis = new FileInputStream(file);
				int length = 0;
				byte[] buffer = new byte[1024*100];
				while ((length = fis.read(buffer))!= -1){
					imgBuffer.append(new String(buffer, 0, length));
				}
				fis.close();
				Matcher m = Pattern.compile("src=\"?(.*?)(\"|>|\\s+)").matcher(imgBuffer.toString()); // 匹配src
				while (m.find()) {
					pics.add(m.group(1));
				}
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}else{
			String regEx_img = "<img.*src=(.*?)[^>]*?>"; // 圖片連結地址
			p_image = Pattern.compile(regEx_img, Pattern.CASE_INSENSITIVE);
			m_image = p_image.matcher(htmlStr);
			while (m_image.find()) {
				imgBuffer.append(",").append(m_image.group());
				Matcher m = Pattern.compile("src=\"?(.*?)(\"|>|\\s+)").matcher(imgBuffer.toString()); // 匹配src
				while (m.find()) {
					pics.add(m.group(1));
				}
			}
			if (pics.size()>0) {
				File cacheFile = new File(CACHE_PATH + "/" + cache_file_name);
				try {
					FileOutputStream fos = new FileOutputStream(cacheFile);
					fos.write(imgBuffer.toString().getBytes());
					fos.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
		return pics;
	}

這裡我會將單個網頁已經做了正則匹配後的所有值連線在一起存入快取檔案中。省的再次抓取相同的網頁時又去做正則匹配,耗時。注意兩個地方:一個是圖片連結地址,還有一個是匹配src。我們先找出連結的全地址如<img src="XXX" /> ,然後在做一次正則匹配找到src的值。最後返回單個網頁的所有圖片的連結地址。知道連結地址,接下來你就可以下載圖片了。抓取網頁的<a href="XXX" />連結也類似。至於獲取網頁程式碼只要去讀取該網頁到字串中即可:
/**
	 * 獲取網頁原始碼
	 * 
	 * @param pageUrl
	 * @param encoding
	 * @return
	 */
	public static String getPageSource(String pageUrl, String encoding) {
		StringBuffer sb = new StringBuffer();
		try {
			URL url = new URL(pageUrl);
			BufferedReader in = new BufferedReader(new InputStreamReader(
					url.openStream(), encoding));
			String line;
			while ((line = in.readLine()) != null) {
				sb.append(line);
				sb.append("\n");
			}
			in.close();
		} catch (Exception e) {
			System.err.println(e);
		}
		return sb.toString();
	}
要注意這裡有個網頁編碼引數,根據該網頁的編碼傳入對應的引數,否則可能會出現亂碼情況。網頁抓取說到底就是正則表示式的強悍體現,最近也有再看一些。就寫到這,歡迎大家一起交流。