爬虫中如何获取页面编码类型

获取页面的编码格式的三种方式:

  1. 根据Response中的header获取编码格式
  2. 根据页面标签中的meta获取
  3. 根据页面内容识别自动识别出编码格式,经过测试准确率比较高

三种方式可以结合使用,由于inputStream不能够被复用,但是inputStrem没有clone方法也导致无法克隆
因此需要流转化,这种方式多重比较需要重复进行流转化。

依赖包

我的资源
在这里插入图片描述

工具类

/***  获取页面的编码格式1.根据Response中的header获取编码格式2.根据页面标签中的meta获取3.根据页面内容识别自动识别出编码格式,经过测试准确率比较高三种方式可以结合使用,目前GFCrawer是使用了meta一种,由于inputStream不能够被复用,但是inputStrem没有clone方法也导致无法克隆因此需要流转化,这种方式多重比较需要重复进行流转化*/
package charset;import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;import org.apache.commons.io.IOUtils;import info.monitorenter.cpdetector.io.ASCIIDetector;
import info.monitorenter.cpdetector.io.ByteOrderMarkDetector;
import info.monitorenter.cpdetector.io.CodepageDetectorProxy;
import info.monitorenter.cpdetector.io.JChardetFacade;
import info.monitorenter.cpdetector.io.ParsingDetector;
import info.monitorenter.cpdetector.io.UnicodeDetector;/*** @author weijie 2019年5月8日*/
public class GFCrawerCharset {public static void main(String[] args) {// 判断乱码System.out.println("------判断乱码-------");//gb2312String url = "http://www.people.com.cn/";//utf-8String url2 = "https://blog.csdn.net/dreamzuora";String errorHtml = GFCrawer.GetContent(url, "utf-8");String succHtml = GFCrawer.GetContent(url2);System.out.println("error: " + errorHtml.substring(100, 300));System.out.println("succ: " + succHtml.substring(1000, 1100));boolean b = isErrorCodes(errorHtml);boolean b2 = isErrorCodes(succHtml);System.out.println(b);System.out.println(b2);// meta获取编码System.out.println("-------meta获取编码------");System.out.println(url + "\t" + getCharsetByMeta(url));System.out.println(url2 + "\t" + getCharsetByMeta(url2));// responseHeader获取后端返回的contentType:但是很多网站不会明确返回System.out.println("-------后端头信息编码结果------");System.out.println(url + "\t" + getAutoCharsetByHeader(url));System.out.println(url2 + "\t" + getAutoCharsetByHeader(url2));// 自动判断编码类型System.out.println("-------识别文本信息编码------");cdpInit();System.out.println(url + "\t" + getAutoCharsetByURL(url));System.out.println(url2 + "\t" + getAutoCharsetByURL(url2));}// 解析页面内容自动识别编码类型public static CodepageDetectorProxy cdp = null;static {cdpInit();}public static void cdpInit() {cdp = CodepageDetectorProxy.getInstance();cdp.add(JChardetFacade.getInstance());cdp.add(ASCIIDetector.getInstance());cdp.add(UnicodeDetector.getInstance());cdp.add(new ParsingDetector(false));cdp.add(new ByteOrderMarkDetector());}/*** 判断是否乱码 加上html的判断会出错* * @param html* @return*/public static boolean isErrorCodes(String str) {for (int i = 0, len = str.length(); i < len; i++) {char c = str.charAt(i);// 当从Unicode编码向某个字符集转换时,如果在该字符集中没有对应的编码,则得到0x3f(即问号字符?)//从其他字符集向Unicode编码转换时,如果这个二进制数在该字符集中没有标识任何的字符,则得到的结果是0xfffd//System.out.println("--- " + (int) c);if ((int) c == 0xfffd) {// 存在乱码//System.out.println("存在乱码 " + (int) c);return true;}}return false; }/*** 通过流判断编码格式* * @param in* @return*/public static String getAutoCharsetByInputStream(InputStream in) {String code = null;ByteArrayInputStream bais = null;try {bais = new ByteArrayInputStream(IOUtils.toByteArray(in));Charset charset = cdp.detectCodepage(bais, 2147483647);bais.close();code = charset.name();} catch (IOException e) {e.printStackTrace();}return code;}/*** 通过url判断* * @param href* @return*/public static String getAutoCharsetByURL(String href) {URL url;String code = null;try {url = new URL(href);Charset charset = cdp.detectCodepage(url);code = charset.name();} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return code;}/*** 从mata获取编码格式* * @param url* @return*/public static String getCharsetByMeta(String href) {String charset = null;URL url = null;try {url = new URL(href);} catch (MalformedURLException e) {e.printStackTrace();url = null;} if(url == null){return null;}HttpURLConnection httpConnection = null;try {httpConnection = (HttpURLConnection) url.openConnection();} catch (IOException e) {e.printStackTrace();httpConnection = null;}if(httpConnection == null){return null;}httpConnection.setRequestProperty("User-Agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)");InputStream input = null;try {input = httpConnection.getInputStream();input.read();BufferedReader reader = new BufferedReader(new InputStreamReader(input));while (reader.ready()) {String line = reader.readLine();if (line.contains("http-equiv") && line.contains("charset")) {String tmp = line.split(";")[1];charset = tmp.substring(tmp.indexOf("=") + 1, tmp.indexOf("\""));break;} else {continue;}}reader.close();} catch (Exception e) {e.printStackTrace();input = null;}return charset;}/*** 从mata获取编码格式* * @param url* @return*/public static String getCharsetByMeta(InputStream inputStream) {String charset = null;try {BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));while (reader.ready()) {String line = reader.readLine();if (line.contains("http-equiv") && line.contains("charset")) {String tmp = line.split(";")[1];charset = tmp.substring(tmp.indexOf("=") + 1, tmp.indexOf("\""));} else {continue;}}reader.close();return charset;} catch (MalformedURLException e) {e.printStackTrace();return charset;} catch (IOException e) {e.printStackTrace();return charset;}}/*** 从header中获取页面编码* * @param strUrl* @return*/public static String getAutoCharsetByHeader(String href) {String charset = null;URL url = null;try {url = new URL(href);} catch (MalformedURLException e) {e.printStackTrace();url = null;} if(url == null){return null;}HttpURLConnection httpConnection = null;try {httpConnection = (HttpURLConnection) url.openConnection();} catch (IOException e) {e.printStackTrace();httpConnection = null;}if(httpConnection == null){return null;}httpConnection.setRequestProperty("User-Agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)");// 获取链接的headerMap<String, List<String>> headerFields = httpConnection.getHeaderFields();// 判断headers中是否存在Content-Typeif (headerFields.containsKey("Content-Type")) {// 拿到header 中的 Content-Type :[text/html; charset=utf-8]List<String> attrs = headerFields.get("Content-Type");String[] as = attrs.get(0).split(";");for (String att : as) {if (att.contains("charset")) {charset = att.split("=")[1];}}}return charset;}/*** 从header中获取页面编码* * @param strUrl* @return*/public static String getCharsetByHeader(URLConnection urlConn) {String charset = null;// 获取链接的headerMap<String, List<String>> headerFields = urlConn.getHeaderFields();// 判断headers中是否存在Content-Typeif (headerFields.containsKey("Content-Type")) {// 拿到header 中的 Content-Type :[text/html; charset=utf-8]List<String> attrs = headerFields.get("Content-Type");String[] as = attrs.get(0).split(";");for (String att : as) {if (att.contains("charset")) {charset = att.split("=")[1];}}}return charset;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508808.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spark集群部署与架构

在大数据时代&#xff0c;处理海量数据需要分布式计算框架。Apache Spark作为一种强大的大数据处理工具&#xff0c;可以在集群中高效运行&#xff0c;处理数十TB甚至PB级别的数据。本文将介绍如何构建和管理Spark集群&#xff0c;以满足大规模数据处理的需求。 Spark集群架构…

java核心技术-多线程并发设计原理以及常见面试题

文章目录写在前面多线程回顾Thread和Runnable面试官&#xff1a;为什么我们在项目中推荐使用使用Runnable方法而不用继承Thread&#xff1f;面试官&#xff1a;Callable为什么可以带返回值&#xff0c;你知道底层原理&#xff1f;面试题&#xff1a;线程了解&#xff1f;给我讲…

java核心技术-jvm基础知识

文章目录JVM回顾JVM、JRE、JDK之间关系&#xff1f;Java程序执行过程&#xff1f;面试官&#xff1a;解释执行和JIT(及时编译)两种执行方式有什么区别&#xff1f;java虚拟机内存管理jvm整体架构JVM只是定义内存划分规范等&#xff0c;具体实现依赖不同虚拟机实现&#xff0c;如…

多线程场景下利用ThreadLocal是线程安全?

文章目录背景多线程场景测试代码结论背景 ThreadLocal原理以及基本概念这里我就不介绍了&#xff0c;这里我们主要关注ThreadLocal是否是线程安全吗&#xff1f;其实如果我们知道ThreadLocal原理我们肯定知道它是线程安全的&#xff0c;但是我在开发的时候不放心做了个测试&am…

深入剖析线程池基本原理以及常见面试题详解

文章目录面试官&#xff1a;能给我讲讲线程池的实现原理&#xff1f;线程池类继承关系ThreadPoolExecutor核心数据结构面试官&#xff1a;给我讲讲线程池的有哪些参数&#xff1f;面试官&#xff1a;如何优雅的关闭线程&#xff1f;线程的生命周期面试官&#xff1a;线程池哪五…

设计模式七大设计原则

文章目录设计模式七大设计原则开闭原则里氏替换原则依赖倒置原则接口隔离原则迪米特法则-最少知道原则单一职责原则合成复用原则设计模式 面向对象的三个基本特征&#xff1a; 继承封装多态 设计模式体现了代码的耦合性、内聚性、可维护性、可扩展性、重用性、灵活性。 代码…

从框架源码中学习结构型设计模式

文章目录从框架源码学习结构型设计模式适配器模式应用实例案例一&#xff1a;dubbo框架日志适配器Logger接口日志实现类Logger适配器接口LoggerAdapter实现类Logger日志工厂桥接模式应用场景案例&#xff1a;dubbo源码-远程调用模块channelHandler设计ChannelHandler是一个SPI拓…

MDC日志logback整合使用

MDC日志logback整合使用 为什么使用MDC记录日志&#xff1f; 场景&#xff1a; 由于我的搜索服务并发量比较高&#xff0c;而处理一次搜索请求需要记录多个日志&#xff0c;因此日志特别多的情况下去查一次搜索整个日志打印情况会比较复杂。 解决方案&#xff1a; 可以使用用…

如何合理的配置线程数?

文章目录题记Java并发编程实战美团技术团队追求参数设置合理性线程池参数动态化题记 我想不管是在面试中、还是工作中&#xff0c;我们总会面临这种问题&#xff0c;那么到底有没有一种计算公式去告诉我们如何去配置呢&#xff1f; 答案是&#xff1a;没有 想要合理的配置线…

基于CompletableFuture并发任务编排实现

文章目录并发任务编排实现不带返回值/参数传递任务串行执行并行执行并行执行-自定义线程池阻塞等待&#xff1a;多并行任务执行完再执行任意一个任务并发执行完就执行下个任务串并行任务依赖场景带返回值/参数传递任务带返回值实现串行执行多线程任务串行执行对任务并行执行&am…

搜索研发工程师需要掌握的一些技能

文章目录基础语言数据结构与算法工程方面搜索相关搜索主要模块电商搜索流程分词相关搜索召回相似度算法相关词推荐排序相关国美搜索搜索算法工程师需要掌握的技能基础 语言 大部分公司用的是Solr、ElasticSearch&#xff0c;都是基于Java实现的&#xff0c;因此熟悉掌握Java语…

Flink入门看完这篇文章就够了

文章目录第一章&#xff1a;概述第一节&#xff1a;什么是Flink&#xff1f;第二节&#xff1a;Flink特点&#xff1f;第三节&#xff1a;Flink应用场景&#xff1f;第四节&#xff1a;Flink核心组成第五节&#xff1a;Flink处理模型&#xff1a;流处理和批处理第六节&#xff…

word小结

域代码/域结果显示设置 word选项---->>高级------>>显示域代码而非域值将样式传给其它文件使用 首先启动Word打开包含这些样式的一个文件&#xff0c;然后选择“工具”---->“模板和加载项”。在弹出的对话框中单击“管理器”按钮。在弹出的“管理器”对话框中&…

线程属性总结

今天面试那哥们问起线程属性&#xff0c;me竟然就说出了一个&#xff0c;囧 学习&#xff1a;http://blog.csdn.net/zsf8701/article/details/7842392 http://blog.csdn.net/jxhnuaa/article/details/3254299 http://blog.sina.com.cn/s/blog_9bd573450101hgdr.html int pthre…

百度2015校园招聘软件开发笔试题及答案

简单题&#xff08;本题共30分&#xff09; 请简述Tcp-ip的3次握手以及4次挥手过程&#xff1f;并解释为何关闭连接需要4次挥手(10分) 详细答案参见TCP/IP协议三次握手与四次握手流程解析 TCP三次握手、四次挥手过程如下: 通常情况下&#xff0c;一个正常的TCP连接&#xf…

linux ps 命令使用

Linux中的ps命令是Process Status的缩写。ps命令用来列出系统中当前运行的那些进程。ps命令列出的是当前那些进程的快照&#xff0c;就是执行ps命令的那个时刻的那些进程&#xff0c;如果想要动态的显示进程信息&#xff0c;就可以使用top命令。 linux上进程有5种状态 ps命令使…

UML序列图总结

序列图主要用于展示对象之间交互的顺序。 序列图将交互关系表示为一个二维图。纵向是时间轴&#xff0c;时间沿竖线向下延伸。横向轴代表了在协作中各独立对象的类元角色。类元角色用生命线表示。当对象存在时&#xff0c;角色用一条虚线表示&#xff0c;当对象的过程处于激活…

UML用例图总结

用例图主要用来描述 用户、需求、系统功能单元 之间的关系。它展示了一个外部用户能够观察到的系统功能模型图。 【用途】&#xff1a;帮助开发团队以一种可视化的方式理解系统的功能需求。 用例图所包含的元素如下&#xff1a; 1. 参与者(Actor) 表示与您的应用程序或…

Linux网络编程常见面试题

概述 TCP和UDP是网络体系结构TCP/IP模型中传输层一层中的两个不同的通信协议。 TCP&#xff1a;传输控制协议&#xff0c;一种面向连接的协议&#xff0c;给用户进程提供可靠的全双工的字节流&#xff0c;TCP套接口是字节流套接口(stream socket)的一种。UDP&#xff1a;用户…