liubang000 2011-06-10
Nutch爬虫爬取某网页是出现下列异常:
ERROR http.Http (?:invoke0(?)) - java.io.IOException: unzipBestEffort returned null
ERRORhttp.Http(?:invoke0(?))-atorg.apache.nutch.protocol.http.api.HttpBase.processGzipEncoded(HttpBase.java:472)
ERRORhttp.Http(?:invoke0(?))-atorg.apache.nutch.protocol.http.HttpResponse.<init>(HttpResponse.java:151)
ERRORhttp.Http(?:invoke0(?))-atorg.apache.nutch.protocol.http.Http.getResponse(Http.java:63)
ERRORhttp.Http(?:invoke0(?))-atorg.apache.nutch.protocol.http.api.HttpBase.getProtocolOutput(HttpBase.java:208)
ERROR http.Http (?:invoke0(?)) - at org.apache.nutch.fetcher.Fetcher$FetcherThread.run(Fetcher.java:173)经过调试发现异常来源于:
java.io.IOException: Not in GZIP format
atjava.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:137)
atjava.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:58)
atjava.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:68)
该异常原因:此页面采用这个是一个分段传输,而nutch爬虫则默认采用了非分段式处理,导致构造GZIP时出错,从而影响了后面的GZIP解压失败。
是否是分段传输可以在Http headers里面看到,如果是分段传输则有:transfer-encoding:chunked这样一个响应。
处理方法:
1. 修改接口org.apache.nutch.metadata.HttpHeaders, 添加:
public final static String TRANSFER_ENCODING = "Transfer-Encoding";
2. 在nutch中的org.apache.nutch.protocol.http.HttpResponse类中已经提供了分段传输类型的处理方法:
private void readChunkedContent(PushbackInputStream in, StringBuffer line)
我们只需要在HttpResponse的构造方法总调用该方法即可,添加如下代码:
String transferEncoding = getHeader(Response.TRANSFER_ENCODING); if(transferEncoding != null && transferEncoding.equalsIgnoreCase("chunked")){ StringBuffer line = new StringBuffer(); this.readChunkedContent(in, line); }else{ readPlainContent(in); }
修改完成,运行测试。
刚才不能爬取的站点终于可以爬取了