我正在制作一个与rss相关的应用程序。
我希望能够下载rss(xml),只提供包含以下内容的网站url:
link rel=“alternate”type=“应用程序/rss+xml”
例如,http://www.engaget.com源包含:
<link rel="alternate" type="application/rss+xml" title="Engadget" href="http://www.engadget.com/rss.xml">
我假设如果我以rss应用程序的形式打开这个站点,它会将我重新定向到http://www.engadget.com/rss.xml页面。
下载XML的代码如下:
private boolean downloadXml(String url, String filename) {
try {
URL urlxml = new URL(url);
URLConnection ucon = urlxml.openConnection();
ucon.setConnectTimeout(4000);
ucon.setReadTimeout(4000);
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is, 128);
FileOutputStream fOut = openFileOutput(filename + ".xml", Context.MODE_WORLD_READABLE | Context.MODE_WORLD_WRITEABLE);
OutputStreamWriter osw = new OutputStreamWriter(fOut);
int current = 0;
while ((current = bis.read()) != -1) {
osw.write((byte) current);
}
osw.flush();
osw.close();
} catch (Exception e) {
return false;
}
return true;
}
如果我不知道“http://www.engadget.com/rss.xml”url,那么当我输入“http://www.engadget.com”时,如何下载rss?
最佳答案
要做到这一点,您需要:
检测URL是否指向HTML文件。请参见下面代码中的isHtml
方法。
如果url指向html文件,则从中提取rss url。请参见下面代码中的extractRssUrl
方法。
以下代码是您在问题中粘贴的代码的修改版本。对于I/O,我将Apache Commons IO用于有用的IOUtils
和FileUtils
类。IOUtils.toString
用于将输入流转换为字符串,如文章“In Java, how do I read/convert an InputStream to a String?中建议的那样。extractRssUrl
使用正则表达式来解析html,即使它非常不受欢迎。(参见“RegEx match open tags except XHTML self-contained tags中的咆哮)记住这一点,让extractRssUrl
成为一个起点。extractRssUrl
中的正则表达式是初步的,并不涵盖所有病例。
注意,对isRss(str)
的调用被注释掉。如果要进行rss检测,请参见“How to detect if a page is an RSS or ATOM feed”。
private boolean downloadXml(String url, String filename) {
InputStream is = null;
try {
URL urlxml = new URL(url);
URLConnection ucon = urlxml.openConnection();
ucon.setConnectTimeout(4000);
ucon.setReadTimeout(4000);
is = ucon.getInputStream();
String str = IOUtils.toString(is, "UTF-8");
if (isHtml(str)) {
String rssURL = extractRssUrl(str);
if (rssURL != null && !url.equals(rssURL)) {
return downloadXml(rssURL, filename + ".xml");
}
} else { // if (isRss(str)) {
// For now, we'll assume that we're an RSS feed at this point
FileUtils.write(new File(filename), str);
return true;
}
} catch (Exception e) {
// do nothing
} finally {
IOUtils.closeQuietly(is);
}
return false;
}
private boolean isHtml(String str) {
Pattern pattern = Pattern.compile("<html", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE);
Matcher matcher = pattern.matcher(str);
return matcher.find();
}
private String extractRssUrl(String str) {
Pattern pattern = Pattern.compile("<link(?:\\s+href=\"([^\"]*)\"|\\s+[a-z\\-]+=\"[^\"]*\")*\\s+type=\"application/rss\\+(?:xml|atom)\"(?:\\s+href=\"([^\"]*)\"|\\s+[a-z\\-]+=\"[^\"]*\")*?\\s*/?>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE);
Matcher matcher = pattern.matcher(str);
if (matcher.find()) {
for (int i = 1; i <= matcher.groupCount(); i++) {
if (matcher.group(i) != null) {
return matcher.group(i);
}
}
}
return null;
}
以上代码适用于engadget示例:
obj.downloadXml("http://www.engadget.com/", "rss");