首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >解决java的http请求库dongliu.requests请求结果中文乱码的问题

解决java的http请求库dongliu.requests请求结果中文乱码的问题

作者头像
LCyee
发布2020-08-05 17:02:14
1.2K0
发布2020-08-05 17:02:14
举报

前言

在前几天接到一个需求,需要爬取某个网站上的一些数据,并且经过整理后将爬取到的数据写入到数据库内。

这类需求如果不需要考虑太多性能的问题的话,使用 Python 来实现的效率是最高的,但考虑到后续可能需要作为模块整合至springboot 的应用内,所以还是决定使用 java 的库来进行开发。

在这之前了解到并且使用的 javahttp 库都是 okhttphttpclientRestTemplate 等,虽然这些库也简化了很多原生求的复杂配置过程,但对于一些需求还是需要自行去封装,操作体验和开发效率上都差了很多。

所以突发奇,在java庞大的生态里面,有无类似 pythonrequests 这类体验更好的 http 请求库? 经过一番搜索后,在 github 上找到了与该库同名的一个 http 库,该模块的作者的灵感也同样来自于 Python 的第三方 库 requests,描述如下

Requests is a http request lib with fluent api for java, inspired by the python request module. Requests requires JDK 1.8+, the last version support Java7 is 4.18.* . 一个具有流畅java api的http请求库,灵感来自python请求模块。请求需要JDK 1.8+,最后一个支持Java7的版本是4.18.* (中文为机器翻译)

经过一番体验后,该模块确实提供了很多便捷的java api,简化了大量的配置流程。

具体的使用方法,参考该模块的开源仓库:https://github.com/hsiafan/requests

问题描述

请求返回的数据内包含了中文,而 Requests 模块默认使用的是 utf-8 编码来解析响应的数据,代码如下

public class RequestsDemo {
    public static void main(String[] args) {
        String url = "http://example.com/index.asp";
        //请求头
        Map<String, Object> headers = new HashMap<>();
        headers.put("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36");
        //请求信息
        Map<String, Object> formData = new HashMap<>();
        formData.put("username", "666");
        formData.put("passwd", "666");
        formData.put("login", "%B5%C7%A1%A1%C2%BC");
        Session session = Requests.session();
        String respText = session.post(url)
            //设置请求头
            .headers(headers)
            .requestCharset(Charset.forName("gbk"))
            //请求表单
            .body(formData)
            //发送请求
            .send().readToText();
        System.out.println(respText);
    }
}

请求返回的结果如下图

image.png
image.png

从上图可以看出中文的内容都变成了乱码。

发现了两个与编码相关的api

但通过 charset 进行编码的设置后,请求返回的结果仍然是乱码,无奈只能寻求其他的解决方案。

在后续的反思当中,觉着事情没这么简单,经过大量版本迭代的一个优秀的http库怎么会由如此弱鸡的问题?最后发现是api调用循序的问题导致无法根据指定的编码格式对响应的数据进行解码,详细请看 方案2 的过程描述。

解决方案

方案1

使用 .readToBytes()bytes 形式结果获取响应的数据,然后再将 bytes 转为 gb2312 编码的 String 字符串,最终得到预期编码的结果,代码如下

Session session = Requests.session();
//发送请求
byte[] readToBytes = session.post(url)
	//设置请求头
	.headers(headers)
	//请求表单
	.body(formData)
	//发送请求
	.send().readToBytes();
//将请求结果进行解码
try {
	String gb2312 = new String(readToBytes, "gb2312");
	System.out.println(gb2312);
} catch (UnsupportedEncodingException e) {
	e.printStackTrace();
}

执行结果如下

成功获取解析带有中文的响应结果。

方案2

而在提出 方案1 的解决方案后又想到可能是因为 api 调用顺序的问题,于是翻阅到了一篇文章,发现对于编码的案例是在 .send() 之后调用了 withCharset().withCharset() 已被官方替换为 .charset()

由于目前网上对于这个开源类库的内容比较少,所以在这之前没有搜索到合适的案例

废话少说,直接上代码。

//发送请求
String respStr = session.post(url)

	//设置请求头
	.headers(headers)
	//请求表单
	.body(formData)
	//发送请求
	.send().charset(Charset.forName("gb2312")).readToText();
System.out.println(respStr);

响应结果如下

image.png
image.png

官方给出的解释如下

image.png
image.png

由于之前没有仔细阅读官方的文档,耗进去了不少的时间去去寻找其他的解决办法(机翻的英文有点曲解了意思,奈何纯英文的文档又看不懂)

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=10stzoecdirmx

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 问题描述
  • 解决方案
    • 方案1
      • 方案2
      相关产品与服务
      机器翻译
      机器翻译(Tencent Machine Translation,TMT)结合了神经机器翻译和统计机器翻译的优点,从大规模双语语料库自动学习翻译知识,实现从源语言文本到目标语言文本的自动翻译,目前可支持十余种语言的互译。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档