4

我正在制作一个 RSS 相关的应用程序。
我希望能够下载 RSS(xml) 仅给出包含以下内容的网站 URL:

链接 rel="alternate" 类型="应用程序/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”的网址,我输入“http://www.engadget.com”时如何下载 RSS?

4

2 回答 2

2

为此,您需要:

  1. 检测 URL 是否指向 HTML 文件。请参阅isHtml下面代码中的方法。
  2. 如果 URL 指向 HTML 文件,请从中提取 RSS URL。请参阅extractRssUrl下面代码中的方法。

以下代码是您在问题中粘贴的代码的修改版本。对于 I/O,我将Apache Commons IO用于有用IOUtilsFileUtils类。IOUtils.toString用于将输入流转换为字符串,如文章“ In Java, how do I read/convert an InputStream to a String? ”中推荐的那样。

extractRssUrl使用正则表达式来解析 HTML,尽管它非常不受欢迎。(请参阅“ RegEx 匹配打开的标签,XHTML 自包含标签除外”中的咆哮。)考虑到这一点,让我们extractRssUrl作为一个起点。中的正则表达式extractRssUrl是基本的,并不涵盖所有情况。

请注意,调用isRss(str)被注释掉了。如果要进行 RSS 检测,请参阅“如何检测页面是 RSS 还是 ATOM 提要”。

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");
于 2012-05-08T02:13:33.977 回答
1

我想显而易见的答案是您首先获取您拥有的 URL (http://www.engadget.com),然后查看 HTML 以找到<link>具有正确类型的标签,然后获取其href属性。这是一些(Java)代码:

URL url = new URL("http://www.engadget.com");
InputStream is = url.openStream();
int ptr = 0;
StringBuffer buffer = new StringBuffer();
while ((ptr = is.read()) != -1) {
  buffer.append((char)ptr);
}
String html = buffer.toString();
Pattern rsspatt = Pattern.compile("<link[^>]*rss[^>]*>");
Matcher m = rsspatt.matcher(html);
String link = "";
if (m.find()) {
  String rsslink = m.group();
  Pattern xmllinkpatt = Pattern.compile("href=\"([^\"]+)\"");
  Matcher m2 = xmllinkpatt.matcher(rsslink);
  m2.find();
  link = m2.group(1);
}

在此结束时,该变量link将为空白或包含您想要的链接,您可以将其输入到您的 downloadXml 函数中。

通常我不建议通过正则表达式解析 HTML,但我认为这是针对手机应用程序的,您希望保持简单并尽可能仅使用核心。当然,如果你想变得花哨,你可以使用 Jsoup 来检查链接标签的存在和正确的属性,然后提取你想要的链接。

于 2012-05-08T02:29:10.493 回答