nutch2.0+cassandra中文网页乱码问题

时间:2022-09-26 04:47:42

用nutch2.0+cassandra1.0爬取和存储网页时发现gbk编码的网页解析提取文本时中文全都变成乱码,非常奇怪,之前nutch1.x从来就不会出现中文乱码的问题的,因为nutch1.x和nutch2.x用的爬虫代码差不多是一样的,所以我猜可能是保存到cassandra时有问题。看了下它保存网页到cassandra的源码,所有需要保存的值它都转换成二进制封装成ByteBuffer对象传到gora中持久化。看下gora-cassandra的源码中操作cassandra的部分

CassandraClient.java中,addColumn添加数据,值为ByteBuffer的则转换成字符串

public void addColumn(String key, String fieldName, Object value) {
if (value == null) {
return;
}
if (value instanceof ByteBuffer) {
value = toString((ByteBuffer) value);
}

String columnFamily = this.cassandraMapping.getFamily(fieldName);
String columnName = this.cassandraMapping.getColumn(fieldName);

this.mutator.insert(key, columnFamily, HFactory.createStringColumn(columnName, value.toString()));
}

ByteUtils.java中把byte转换成字符串的代码

public static String toString(final byte [] b, int off, int len) {
if(b == null) {
return null;
}
if(len == 0) {
return "";
}
String result = null;
try {
result = new String(b, off, len, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}

坑爹了,直接就转换成UTF-8保存的,也就是说爬下gbk编码的网页,它把gbk编码转成了UTF-8的字符串,保存到cassandra中,本来这样转换成utf-8也没问题的,不过后来到nutch执行解析的时候,由于nutch的提取页面编码算法比较偏向于请求头的编码(如果请求头没有就提取文件进行计算猜测),而此时的charset=gbk,也就gbk编码。原来utf-8存储到cassandra的数据去出来时转换成了gbk编码,不乱码才怪,知道了原因,要解决就好办了。

我在想为什么它不直接就用二进制的格式存储,这样感觉效率要高点,然后就又看到了CassandraClient.java中的toString方法,还有个TODO注释在那,说不要把二进制的字段从字节转换成字符串存储,原来是还没有完善的。

/**
* TODO do no convert bytes to string to store a binary field
* @param value
* @return
*/
private static String toString(ByteBuffer value) {
ByteBuffer byteBuffer = (ByteBuffer) value;
return ByteUtils.toString(byteBuffer.array(), 0, byteBuffer.limit());
}

于是就到git上看了下gora0.3版的代码,果然改了,不直接转换成字符串存储了,原来还想自己解决,看来又省了,最简单的解决方法就是把nutch2.0的gora依赖库从0.2,改成0.3