Closed keatonLiu closed 1 year ago
现在的 Site.charset 就是这么用的吧:
request.getCharset() != null ? request.getCharset() : task.getSite().getCharset()
如果请求中没有获得 charset,就用 site 设置的 charset。
请求中是获取不到charset的,charset是在响应里面获取,也就是在handleResponse()
里面获取,这里面一段代码获取chaset:
只有request.getCharset() != null ? request.getCharset() : task.getSite().getCharset()返回结果为null的时候他才会自动推断charset
现在的代码里的 charset 的使用顺序是, request charset, site charset, html charset, jvm default charset. 你的意思是,需要再来一个 default charset, 按照这个顺序: request charset, site charset, html charset, default charset, jvm default charset?
是,差不多这个意思,我是想的是这个site charset只有在自动推断失效才会使用,这样就不用default charset了。 现在的情况是,只有request charset, site charset同时为null才会使用自动推断,而且会发出警告,如果推断失败,回退到的默认编码也只有utf-8。
我的想法是,首先让这个函数推断失败时直接返回null:
然后把使用默认编码的判断放在这里:
protected Page handleResponse(Request request, String charset, HttpResponse httpResponse, Task task) throws IOException {
byte[] bytes = IOUtils.toByteArray(httpResponse.getEntity().getContent());
String contentType = httpResponse.getEntity().getContentType() == null ? "" : httpResponse.getEntity().getContentType().getValue();
Page page = new Page();
page.setBytes(bytes);
if (!request.isBinaryContent()) {
String detectedCharset = this.getHtmlCharset(contentType, bytes);
if (detectedCharset == null) {
if (charset == null){
charset = Charset.defaultCharset().name();
logger.warn("Charset autodetect failed, use {} as charset. Please specify charset in Site.setCharset()", Charset.defaultCharset());
}
} else {
charset = detectedCharset;
}
page.setCharset(charset);
page.setRawText(new String(bytes, charset));
}
page.setUrl(new PlainText(request.getUrl()));
page.setRequest(request);
page.setStatusCode(httpResponse.getStatusLine().getStatusCode());
page.setDownloadSuccess(true);
if (this.responseHeader) {
page.setHeaders(HttpClientUtils.convertHeaders(httpResponse.getAllHeaders()));
}
return page;
}
建议setCharSet()在通过响应推断编码失败时才使用,或者增加一个setDefaultCharSet(),当推断编码失败时使用该默认编码