nutch2.0+cassandra中文网页乱码问题
用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) {
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