4

RSS関連のアプリを作っています。
以下を含む Web サイト URL のみを指定して、RSS(xml) をダウンロードできるようにしたいと考えています。

リンク rel="alternate" type="application/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 をダウンロードするにはどうすればよいですか?

4

2 に答える 2

2

これを実現するには、次のことを行う必要があります。

  1. URL が HTML ファイルを指しているかどうかを検出します。isHtml以下のコードのメソッドを参照してください。
  2. URL が HTML ファイルを指している場合は、そこから RSS URL を抽出します。extractRssUrl以下のコードのメソッドを参照してください。

次のコードは、質問に貼り付けたコードの修正版です。I/O には、有用なクラスとクラスにApache Commons IOを使用しました。記事「In Java, how do I read/convert an InputStream to a String?」で推奨されているように、入力ストリームを文字列に変換するために使用されます。IOUtilsFileUtilsIOUtils.toString

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 を使用して link タグと適切な属性の存在を確認し、必要なリンクを抽出することができます。

于 2012-05-08T02:29:10.493 に答える