JAVA如何判断网页编码

13 篇文章 0 订阅

前言

  最近做一个搜索项目,需要爬取很多网站获取需要的信息。在爬取网页的时候,需要获得该网页的编码,不然的话会发现爬取下来的网页有很多都是乱码。

 

分析

  一般情况下,网页头信息会指定编码,可以解析header或者meta获得charset。但有时网页并没没有指定编码,这时就需要通过网页内容检测编码格式,通过调研,最好用的还是cpdetector。 

 

1、首先,可从header中解析charset

  网页头信息中的Content-Type会指定编码,如图:

  

  可以通过分析header,查找字符编码,代码如下:

	private static String getEncodingByHeader(URL url) {
		String strencoding = null;
		HttpURLConnection httpConn = null;
		try {
			httpConn = (HttpURLConnection) url.openConnection();
			httpConn.setRequestProperty("User-agent", "Mozilla/4.0");
			Map<String, List<String>> map = httpConn.getHeaderFields();

			Set<String> keys = map.keySet();
			Iterator<String> iterator = keys.iterator();

			// 遍历,查找字符编码
			String key = null;
			String tmp = null;
			while (iterator.hasNext()) {
				key = iterator.next();
				tmp = map.get(key).toString().toLowerCase();
				// 获取content-type charset
				if (key != null && key.equals("Content-Type")) {
					int m = tmp.indexOf("charset=");
					if (m != -1) {
						strencoding = tmp.substring(m + 8).replace("]", "");
						return strencoding;
					}
				}
			}
		} catch (IOException e) {
			strencoding = null;
		} finally {
			try {
				if (httpConn != null)
					httpConn.disconnect();
			} catch (Exception ex) {
				log.error(ex);
			}
		}
		return strencoding;
	}


2、其次,可从网页meta中解析出charset

  正常情况下,在写网页时,会指定网页编码,可在meta中读出来。如图:

  

  首先获取网页流,因为英文和数字不会乱码,可以解析meta,获得charset。

	/**
	 * 从网页meta中解析出charset
	 * 
	 * @param in2
	 * @return
	 */
	private static String getEncodingByMeta(InputStream inputs) {
		String strencoding = null;
		// StringBuffer sb = new StringBuffer();
		String line;
		BufferedReader in = null;
		try {
			in = new BufferedReader(new InputStreamReader(inputs));
			while ((line = in.readLine()) != null) {
				// sb.append(line);
				if (line.contains("<meta") || line.contains("<META")) {
					// 解析html源码,取出<meta />区域,并取出charset
					line = line.toLowerCase();
					String strbegin = "<meta";
					String strend = ">";
					String strtmp;
					int begin = line.indexOf(strbegin);
					int end = -1;
					int inttmp;
					while (begin > -1) {
						end = line.substring(begin).indexOf(strend);
						if (begin > -1 && end > -1) {
							strtmp = line.substring(begin, begin + end)
									.toLowerCase();
							inttmp = strtmp.indexOf("charset");
							if (inttmp > -1) {
								strencoding = strtmp.substring(inttmp + 7, end)
										.replace("=", "").replace("/", "")
										.replace("\"", "").replace("\'", "");
//										.replace(" ", "#");
								if (strencoding.indexOf(" ") != -1) {
									strencoding = strencoding.substring(0, strencoding.indexOf(" "));
								}
								return strencoding;
							}
						}
						line = line.substring(begin);
						begin = line.indexOf(strbegin);
					}
				}
			}
		} catch (Exception e) {
			System.err.println(e);
		} finally {
			if (in != null)
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}

		return null;
	}


3、当使用1、2解析不出编码时,使用cpdetector根据网页内容探测出编码格式

 涉及到的jar包有chardet.jarantlr.jarcpdetector_1.0.7.jar

 可以添加多个编码探测实例:

	public static String getFileCharacterEnding(URL url) {

		String fileCharacterEnding = null;

		CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
		detector.add(JChardetFacade.getInstance());// <span style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; line-height: 25.200000762939453px;"> 需要第三方JAR包:antlr.jar、chardet.jar</span>
		detector.add(ASCIIDetector.getInstance());
		detector.add(UnicodeDetector.getInstance());
		detector.add(new ParsingDetector(false));
		detector.add(new ByteOrderMarkDetector());

		Charset charset = null;
		try {
			charset = detector.detectCodepage(url);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (charset != null) {
			fileCharacterEnding = charset.name();
		}

		return fileCharacterEnding;
	}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值