WARC里的HTTP响应
程序员文章站
2024-02-01 13:14:34
...
WARC是一种格式。Heritrix(http://crawler.archive.org/)用它原封不动地储存HTTP请求和HTTP响应的全文。包括请求/状态行、头、内容。
读WARC格式很简单。利用Heritrix中提供的工具即可。
如果里面储存了爬虫爬的结果,那么整个HTTP响应会成为一条记录的内容。这种记录是原封不动的响应,包括status line, headers, entity,都有。mimetype是application/http,如HTTP/1.1的RFC中所述。
如何解析这个响应呢?
想过用Apache Httpcomponents(http://hc.apache.org/)的HTTP Core,但是它的解析器与Socket耦合太强,还使用了很多自己的数据结构以提高效率。Jetty的解析器没有文档(undocumented)。
最后,发现如果只是想读HTTP头,还是用BufferedReader自己读比较好。
但是,由于BufferedReader的缓冲,此时读出的entity是不正确的。
读WARC格式很简单。利用Heritrix中提供的工具即可。
package warc; import java.io.*; import org.apache.commons.io.IOUtils; import org.archive.io.*; import org.archive.io.warc.*; public class MyWarcReading { public static void main(String[] args) throws Exception { ArchiveReader ar = WARCReaderFactory.get("/path/to/your/file.warc.gz"); // ArchiveReader对象本身实现了Iterator<ArchiveRecord>接口,可以用for循环。 for (ArchiveRecord rec : ar) { // 获取WARC记录头。 ArchiveRecordHeader header = rec.getHeader(); // 可以对header做一些操作。 // 读出这条记录的内容。ArchiveRecord继承了InputStream类。 // 我使用了Commons-IO。不过这样读太暴力了…… byte[] content = IOUtils.toByteArray(rec); // 对内容做什么都行。 } ar.close(); } }
如果里面储存了爬虫爬的结果,那么整个HTTP响应会成为一条记录的内容。这种记录是原封不动的响应,包括status line, headers, entity,都有。mimetype是application/http,如HTTP/1.1的RFC中所述。
ArchiveRecord rec; // 一条记录 if(rec.getHeader().getMimetype().equals( "application/http; msgtype=response")) { // 这是HTTP响应 }
如何解析这个响应呢?
想过用Apache Httpcomponents(http://hc.apache.org/)的HTTP Core,但是它的解析器与Socket耦合太强,还使用了很多自己的数据结构以提高效率。Jetty的解析器没有文档(undocumented)。
最后,发现如果只是想读HTTP头,还是用BufferedReader自己读比较好。
private static void parseHtml(ArchiveRecord rec) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(rec,"ISO-8859-1")); String statusLine = br.readLine(); System.out.println("Status:"+statusLine); System.out.println("===HTTP headers==="); while(true) { String line = br.readLine(); if(line==null || line.isEmpty()) { break; } System.out.println(line); } byte[] bytes = IOUtils.toByteArray(rec); // WRONG! System.out.println("===HTTP entity==="); System.out.println(new String(bytes, "UTF-8")); }
但是,由于BufferedReader的缓冲,此时读出的entity是不正确的。
上一篇: Linux系统开发之路 - 下
下一篇: 赚在当下才是王道千万不要好高骛远