【发布时间】:2011-10-10 02:56:23
【问题描述】:
我正在编写一个爬虫/解析器,它应该能够处理不同类型的内容,包括 RSS、Atom 和纯 html 文件。为了确定正确的解析器,我编写了一个名为 ParseFactory 的类,它接受一个 URL,尝试检测内容类型,并返回正确的解析器。
不幸的是,使用 URLConnection 中提供的 in 方法检查内容类型并不总是有效。例如,
String contentType = url.openConnection().getContentType();
并不总是提供正确的内容类型(例如“text/html”应该是 RSS)或者不允许区分 RSS 和 Atom(例如“application/xml”可能是 Atom 或RSS 提要)。为了解决这个问题,我开始在 InputStream 中寻找线索。问题是我在想出一个优雅的类设计时遇到了麻烦,我只需要下载一次 InputStream。在我当前的设计中,我首先编写了一个单独的类来确定正确的内容类型,接下来 ParseFactory 使用此信息创建相应解析器的实例,而当调用“parse()”方法时,下载整个 InputStream 第二次。
public Parser createParser(){
InputStream inputStream = null;
String contentType = null;
String contentEncoding = null;
ContentTypeParser contentTypeParser = new ContentTypeParser(this.url);
Parser parser = null;
try {
inputStream = new BufferedInputStream(this.url.openStream());
contentTypeParser.parse(inputStream);
contentType = contentTypeParser.getContentType();
contentEncoding = contentTypeParser.getContentEncoding();
assert (contentType != null);
inputStream = new BufferedInputStream(this.url.openStream());
if (contentType.equals(ContentTypes.rss))
{
logger.info("RSS feed detected");
parser = new RssParser(this.url);
parser.parse(inputStream);
}
else if (contentType.equals(ContentTypes.atom))
{
logger.info("Atom feed detected");
parser = new AtomParser(this.url);
}
else if (contentType.equals(ContentTypes.html))
{
logger.info("html detected");
parser = new HtmlParser(this.url);
parser.setContentEncoding(contentEncoding);
}
else if (contentType.equals(ContentTypes.UNKNOWN))
logger.debug("Unable to recognize content type");
if (parser != null)
parser.parse(inputStream);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return parser;
}
基本上,我正在寻找一种解决方案,可以让我消除第二个“inputStream = new BufferedInputStream(this.url.openStream())”。
任何帮助将不胜感激!
旁注 1:为了完整起见,我也尝试使用 URLConnection.guessContentTypeFromStream(inputStream) 方法,但这经常返回 null。
附注 2:XML 解析器(Atom 和 Rss)基于 Jsoup 上的 Html 解析器 SAXParser。
【问题讨论】:
标签: java content-type inputstream