Nutch:contentデータの文字化け対策
Nutch*1メモ。
SegmentReaderでcontentデータをdumpすると、UTF-8以外の文字コードが文字化けする。
SegmentReader実行時の引数はこんな感じ。
-dump crawl/segments/[0-9]{14} crawl/segments/[0-9]{14}/dumped_text -nofetch -noparsetext -noparse -nogenerate -noparsedata
とりあえずの解決法
HttpResponseクラスのコンストラクタの
readPlainContent(in); String contentEncoding = getHeader(Response.CONTENT_ENCODING); if ("gzip".equals(contentEncoding) || "x-gzip".equals(contentEncoding)) { content = http.processGzipEncoded(content, url); } else if ("deflate".equals(contentEncoding)) { content = http.processDeflateEncoded(content, url); } else { if (Http.LOG.isTraceEnabled()) { Http.LOG.trace("fetched " + content.length + " bytes from " + url); } }
この部分の直後に
analyzeEncoding(content);
こいつを追加。
で、そのメソッドが以下。(問題があったため09/07/06に修正)
private void analyzeEncoding(byte[] contentIn) throws IOException { byte[] buf = new byte[Http.BUFFER_SIZE]; UniversalDetector detector = new UniversalDetector(null); int nread; BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(contentIn)); in.mark(Http.BUFFER_SIZE * 10); while ((nread = in.read(buf)) > 0 && !detector.isDone()) { detector.handleData(buf, 0, nread); } in.reset(); detector.dataEnd(); String encoding = detector.getDetectedCharset(); if (encoding != null) { System.out.println("Detected encoding = " + encoding); } else { System.out.println("No encoding detected."); encoding = "UTF-8"; } detector.reset(); content = (new String(contentIn, encoding)).getBytes(); }
失敗メモ
readPlainContent(in);
このメソッド内で文字コード判別してから保存すると、そのあとのgzipの処理でエラーが発生。
というわけで、gzip処理後に文字コード判別が正解っぽい。
ちなみに
この書き換えを行うと、contentデータは文字化けしないけど、パースした後のデータが文字化けする。
多分HTMLのcharsetとかを見て文字コード判別してるせいかな?
↑と同じDetector使えば良いのかも。
でもパースしたデータは使わないので無視。
というか
こんな事しないでmetaタグのContent-Type見れば早かったかも。