最近在开发ICP备案查询网,为了保持运行的稳定性,虽然我已经拥有不用验证码的ICP备案查询:https://www.sojson.com/beian/
但是还是不能放弃域名(www.xbeian.com),故开发一套产品出来。下面来一个不成型的界面当封面图吧。
废话不说了,开始这篇的分享内容。
1.从工信部页面(“http://www.beian.miit.gov.cn/icp/publish/query/icpMemoInfo_showPage.action”)获取验证码。
2.填写查询内容。
3.填写验证码,提交查询内容,获取查询结果。
中文参数问题:
我们现在项目一般都是UTF-8
的了,但是这个页面是GBK
的。关于编码可以自己看请求头。
有一个头痛的问题就是汉字会编码,就是表单提交编码问题,而 Jsoup 目前自身没有指定编码的方法。。
页面GBK
编码—> URLEncode
编码—>提交到服务器
“刘飞
” GBK的URLEncode
编码后为 “%C1%F5%B7%C9
”,如果你直接转码成这样,通过Jsoup.data(key,value)
提交后,会变成“%25C1%25F5%25B7%25C9
”,没错,他又一次urlencode
,并且是UTF-8
编码的。
辗转反侧测试了很多次,还是不行。
上代码,这个代码非中文参数,没毛病。
Connection jsoup = Jsoup.connect("http://www.beian.miit.gov.cn/icp/publish/query/icpMemoInfo_searchExecute.action")
.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3")
.header("Pragma", "no-cache")
.header("Cache-Control", "no-cache")
.header("Upgrade-Insecure-Requests", "1")
.header("Connection", "close")
.header("Host", "www.beian.miit.gov.cn")
.header("Referer", "http://www.beian.miit.gov.cn/icp/publish/query/icpMemoInfo_showPage.action")
.header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0")
.header("Accept-Encoding", "gzip, deflate")
.header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
.header("Cookie", session);
jsoup.data("mainUnitNature","-1");
jsoup.data("certType","-1");
jsoup.data("mainUnitCertNo","");
jsoup.data("verifyCode",vcode);
jsoup.data("condition",type);
switch (type){
case "0":
jsoup.data("siteName",java.net.URLEncoder.encode(qtext, "gbk"));
break;
case "1":
jsoup.data("siteDomain",qtext);
break;
case "2":
jsoup.data("siteUrl",qtext);
break;
case "3":
jsoup.data("mainLicense",java.net.URLEncoder.encode(qtext, "gbk"));
break;
case "4":
jsoup.data("siteIp",qtext);
break;
case "5"://中文参数提交
//这里转成GBK,但是URLEncode的编码它是utf-8,所以有问题。
//直接提交GBK的URLEncode编码结果,它还是再次URLEncode编码,也是utf-8编码。
jsoup.data("unitName",new String(qtext.getBytes("gbk")));//java.net.URLEncoder.encode(qtext, "gbk")
break;
}
jsoup.timeout(50000);
Document doc = jsoup.post();
我们知道 Jsoup 支持解析IO
,直接解析 HTML ,或者 URL 对象都可以。用这些我知道能解决,但是我还是想直接通过 Jsoup 来解决,尝试了很久,网上看了很多资料,看了些许源码,最终还是失败了。
当我们遇到Http
请求出现问题了,而又不容易看出问题所在,那么就建议直接用抓包工具,把正常的请求和你模拟的请求进行对比。
对比有几个点:header、text参数、form参数、cookie等等,一般是出在参数、header、cookie问题。本次是参数问题,下面截图对比。
查询资料的时候比较滑稽的是,发现百度里,搜索 Jsoup 乱码,我曾经写的一篇关于 Jsoup 乱码是No 1
排名。
不得不借助 Httpclient 等 Http 请求解决。不管采用什么 Http 开源包请求,只要能getInputStream()
或者直接拿到Html Dom结构
也可以,因为 Jsoup 支持parse IO
,也支持parse HTML
。
我自己有自己的Http 封装的工具。为了大家方便使用,我写了一遍较为原始的Http请求,代码如下,测试好使。
try {
OutputStream outStream = null;
OutputStreamWriter out = null;
URL realUrl = new URL("http://www.beian.miit.gov.cn/icp/publish/query/icpMemoInfo_searchExecute.action");
// 打开和URL之间的连接
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");// 提交模式
conn.addRequestProperty("Connection","close");
conn.addRequestProperty("Host", "www.beian.miit.gov.cn");
conn.addRequestProperty("Content-type", "application/x-www-form-urlencoded; charset=gbk");
conn.addRequestProperty("Referer", "http://www.beian.miit.gov.cn/icp/publish/query/icpMemoInfo_searchExecute.action");
conn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0");
conn.addRequestProperty("Cookie", "__jsluid=3f1f3c28f6c3af8b9a7f93418aac4cf1; Hm_lvt_af6f1f256bb28e610b1fc64e6b1a7613=1560086695; Hm_lpvt_af6f1f256bb28e610b1fc64e6b1a7613=1560088421; JSESSIONID=xDlE3rmJFa4RoGaxI_QbVvdJNKbuD-iG_B3Avs_ypkTwQIIoiF-D!-1797433545");
outStream = conn.getOutputStream();
out = new OutputStreamWriter(outStream);
//参数输出
out.write("certType=-1&condition=5&mainUnitNature=-1&unitName=" + java.net.URLEncoder.encode("刘飞", "gbk") +"&verifyCode=666666");
// flush输出流的缓冲
out.flush();
Document doc = Jsoup.parse(conn.getInputStream(), "GBK", "http://www.beian.miit.gov.cn/icp/publish/query/icpMemoInfo_showPage.action");
System.out.println(doc.html());
} catch (IOException e) {
e.printStackTrace();
}
秀一下我封装的Http工具类请求,我比较喜欢链式编程。
String res = Http.create("http://www.beian.miit.gov.cn/icp/publish/query/icpMemoInfo_searchExecute.action")
.cookies("cookie")
.charset("gbk")
.head("Referer","http://www.beian.miit.gov.cn/icp/publish/query/icpMemoInfo_showPage.action")
.head("User-Agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36")
.head("Host","www.beian.miit.gov.cn")
//提交参数
.bodys("siteName=&siteDomain=&siteUrl=&mainLicense=&siteIp=&condition=5&unitName=%D6%DC%B0%D8%B3%C9&mainUnitNature=-1&certType=-1&mainUnitCertNo=&verifyCode=wgqk3k")
.post()
.send()
.getResponse()
.getResult();
Document doc = Jsoup.parse(res);
结果是可以参数编码为GBK
的URLEncode
后提交正确。也对比了抓包,一模一样。
最终还是依赖Http
组件来解决的,如果 Jsoup 解决了的同学,请下面留言,我来补充。
版权所属:SO JSON在线解析
原文地址:https://www.sojson.com/blog/331.html
转载时必须以链接形式注明原始出处及本声明。