JavaでRSSの広告削除してみる(1) Removing Ads from Rss by Java

IT関連の情報サイトから、RSSフィードの情報収集して、その中の単語を解析・集計して、自分用のトレンドランキングをつくろうかと思った。
I come up with making “trend word list” for myself. I try to collect RSS from IT-website, analyze RSS-feed, and rank it.

ためしにRSS受信してみると、RSSフィードの中に広告が入っている場合がある。広告は削除しておきたい。Some RSS contain advertisement. I hope to remove Ads.

RSSから広告削除してくれるサービスがるんだけれども、There are some service to remove Ads from RSS.
RSS広告を削除ならRSS広告削除社

gihyo.jpのRSSの広告がうまく削除されなかった。But, that service didn’t remove Ads from “gihyo.jp”.
というわけで、自分でつくってしまおうかと思った。So I think of trying to make app.

3回に分けて書いていきます。I write this in 3-posts.

第1回 JavaでRSS受信する。 Getting RSS by Java
第2回 HTMLパーサを使う。 Using HTML-parser
第3回 RSSを出力してみる。 Outputting RSS

今回は第1回めです。This is first post.

————————————————————–
使っている環境

Java JDK1.6.0_35(64bit版)
Google App Engine SDK for Java 1.7.1
Eclipse IDE for Java EE Developers_ Juno (4.2)64Bit版
The Google Plugin for Eclipse, for Eclipse 3.8/4.2 (Juno)

ROME 1.0
JDOM 1.1.3
( Xerces 2.11.0 )


(1)はじめに Introduction
JavaのRSSライブラリには、いろいろあるみたい。
There are many library for RSS-reading.
Java や Ruby の RSS/Atom feed ライブラリなど。HTMLからRSSを自動生成……したいなぁ。 (RSS – MemoWiki)

いくつか見てみたんだけど、RSSライブラリはあんまり活発な開発がされてない雰囲気。
どうも、RSSは、昔から使われていて仕様がかたまっているため、ライブラリの改修をする必要があんまり無いっぽい。
で、なんとなく情報量の多そうな、ROMEを使うことにした。
I search RSS-library. But some RSS-library is not active.
I think that RSS-format is so old, and changeless. So, it’s no need to modify RSS-library.


(2)ROME, JDOMのダウンロード  Downloading “ROME and JDOM”
こちらのサイトから、ROMEのダウンロードを行います。僕の場合、rome-1.0.jarをダウンロードしました。
You can download ROME from this site. I downloaded rome-1.0.jar.
Home – ROME – Confluence

ROMEはJDOMと依存関係があるため、こちらのサイトからJDOMもダウンロードします。
ROME have to use with JDOM. So, you should download JDOM from thi site.
JDOM

現時点でJDOM 2.0.5が最新版でしたが、こちらを使うとROMEがうまく動きませんでした。
なので、JDOM 1.1.3を使う必要があります。ダウンロードしたファイルjdom-1.1.3.zipの中のbuildフォルダに、jdom-1.1.3.jarがあるので、これをEclipseのライブラリに追加します。
“JDOM’s latest version 2.0.5” don’t work with ROME. You should use JDOM 1.1.3.
Download jdom-1.1.3.zip, then there is jdom-1.1.3.jar in “build” folder. And add jdom-1.1.3.jar to Eclipse-library.


(3)Xercesのダウンロード Downloading Xerces
こちらは、必要に応じて使うものになります。
単体のJavaアプリとして動かす際には必要ないですが、GAE上でROMEを動かそうとすると、以下のようなエラーが出ます。

Xerces dosn’t need, if you don’t make your Apps on GAE.
But if you use ROME on GAE, you would face this error.

java.lang.IllegalStateException: JDOM could not create a SAX parser
    at com.sun.syndication.io.WireFeedInput.createSAXBuilder(WireFeedInput.java:328)
    at com.sun.syndication.io.WireFeedInput.build(WireFeedInput.java:189)
    at com.sun.syndication.io.SyndFeedInput.build(SyndFeedInput.java:123)
   :   :
   :   :

原因は謎。こちらのサイトによると、Xercesが必要とのこと。
I don’t know Why this error has happen. According to these site, you need Xerces.
Romeが使えない – Google グループ
Issue 1367 – googleappengine – org.apache.xerces.parsers.SAXParser not available – Google App Engine – Google Project Hosting

そのため、こちらのサイトからXercesをダウンロードします。
You can download Xerces from this site.
The Apache Xerces™ Project – xerces.apache.org

ダウンロードしたファイル Xerces-J-bin.2.11.0.tar.gz の中にある、xercesImpl.jarと、xml-apis.jar をEclipseのライブラリに追加します。
Download Xerces-J-bin.2.11.0.tar.gz. In this file, you can get xercesImpl.jar and xml-apis.jar. Then you need to add these Jar-files into Eclipse-library.


(4)コーディング Coding
こちらのサイトを参考にしました。
This site will help you.
JavaのRSSライブラリ、ROMEを使ってみる
RSS・Atomフィードのためのライブラリ”ROME” – argius note
Kazuhiro’s Weblog: Javaで手軽にフィード(RSS、Atom)を扱うライブラリ 「ROME」

RSS取得時のコードは以下のような書き方になります。
You can get RSS with this code.

        String url = "http://jp.techcrunch.com/feed/";

        URL feedUrl = new URL(url);
        XmlReader reader = new XmlReader(feedUrl.openStream());
            SyndFeedInput input = new SyndFeedInput();
            SyndFeed feed = input.build(reader);
        reader.close();

上記では取得したデータが、feedの中に格納されています。
feed.getTitle()といった形で、個々のデータが取得できます。
RSSの1つ1つの記事は、feed.getEntries()でまとめて取得できます。List形式のデータになっています。

That code will give you RSS-data in  a variable “feed”.
You can get each a RSS-element using the method “feed.getTitle()”.
And you can get a RSS-entry using the method “feed.getEntries()”.

とりあえず、取得したデータをすべて表示してみることにしました。最終的なソースコードを以下にまとめて記載します。
I could show you each elements in RSS., If you use this code.

RomeSample3.java

import java.net.URL;
import java.util.List;

import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;

public class RomeSample3 {
    public static void main(String[] args) throws Exception {
        // String url = "http://rss.rssad.jp/rss/gihyo/feed/rss2";

        // String url = "http://rss.dailynews.yahoo.co.jp/fc/rss.xml";
        String url = "http://jp.techcrunch.com/feed/";
        // String url = "http://wired.jp/rssfeeder/";

        URL feedUrl = new URL(url);
        XmlReader reader = new XmlReader(feedUrl.openStream());
            SyndFeedInput input = new SyndFeedInput();
            SyndFeed feed = input.build(reader);
        reader.close();

        // ###########################################################
        System.out.println("----- Site Infomation ----------------------------------");
        System.out.println("SITE author : " + feed.getAuthor());
        System.out.println("SITE authors : " + feed.getAuthors());
        System.out.println("SITE categories : " + feed.getCategories());
        System.out.println("SITE contributors : " + feed.getContributors());
        System.out.println("SITE Copyright : " + feed.getCopyright());
        System.out.println("SITE description : " + feed.getDescription());
        System.out.println("SITE DescriptionEx : " + feed.getDescriptionEx());
        System.out.println("SITE encoding : " + feed.getEncoding());
        System.out.println("SITE feedType : " + feed.getFeedType());
        System.out.println("SITE ForeignMarkup : " + feed.getForeignMarkup());
        System.out.println("SITE image : " + feed.getImage());
        System.out.println("SITE language : " + feed.getLanguage());
        System.out.println("SITE link : " + feed.getLink());
        System.out.println("SITE links : " + feed.getLinks());
        // System.out.println("SITE Module : " + feed.getModule(url));
        // System.out.println("SITE Modules : " + feed.getModules());
        System.out.println("SITE getPublishedDate : " + feed.getPublishedDate());
        System.out.println("SITE getSupportedFeedTypes : " + feed.getSupportedFeedTypes());
        System.out.println("SITE title : " + feed.getTitle());
        System.out.println("SITE getTitleEx : " + feed.getTitleEx());
        System.out.println("SITE uri : " + feed.getUri());

        // ###########################################################
        List<SyndEntry> entries = feed.getEntries();

        Integer i = 1;
        for (SyndEntry entry : entries) {
            System.out.println("----- Entries No." + i + "----------------------------------");
            System.out.println("ENTRY Author : " + entry.getAuthor());
            System.out.println("ENTRY Authors : " + entry.getAuthors());
            System.out.println("ENTRY Categories : " + entry.getCategories());
            System.out.println("ENTRY Contents : " + entry.getContents());
            System.out.println("ENTRY Contributors : " + entry.getContributors());
            System.out.println("ENTRY Description : " + entry.getDescription());
            System.out.println("ENTRY Enclosures : " + entry.getEnclosures());
            System.out.println("ENTRY ForeignMarkup : " + entry.getForeignMarkup());
            System.out.println("ENTRY Link : " + entry.getLink());
            System.out.println("ENTRY Links : " + entry.getLinks());
            // System.out.println("ENTRY Module : " + entry.getModule(url));
            // System.out.println("ENTRY Modules : " + entry.getModules());
            System.out.println("ENTRY PublishedDate : " + entry.getPublishedDate());
            System.out.println("ENTRY Source : " + entry.getSource());
            System.out.println("ENTRY Title : " + entry.getTitle());
            System.out.println("ENTRY TitleEx : " + entry.getTitleEx());
            System.out.println("ENTRY UpdatedDate : " + entry.getUpdatedDate());
            System.out.println("ENTRY Uri : " + entry.getUri());
            System.out.println("ENTRY WireEntry : " + entry.getWireEntry());
            System.out.println("");

            i = i + 1;
        }
    }
}

これで、RSSの受信はできました。I could get RSS.

ほしい情報は、記事のタイトルと要約の部分になります。ソース上では以下の部分。
Title and Descriptin are important for me. I can get those using this method .

entry.getTitle()
entry.getDescription()

実際にRSS取得してみると、記事丸ごとが広告になっている場合と、要約の中に広告が埋まっている場合があります。
タイトルが”PR:”で始まっているものは、記事全体が広告になってる。これはタイトルの文字列をチェックするだけなので取り除くのは簡単です。
要約の中に広告が埋まっている場合は、以下のような形で、広告のリンクが埋まっています。

I got RSS-feed, then I found that there is some Ads in RSS. Some entry are ads, and some RSS-description has ads.
If “Title” start with “PR:” , RSS-entry is a advertisement. It’s easy to check “Title”.
But if RSS-description had ads, it’s difficult to remove ads.
This is sample that there are “link to ads” in description.

<p>前回紹介したように,gmtpに文字コード回りのパッチをあてることで,無事Plamo Linux環境とNexus 7の間でファイルをやりとりできるようになりました。しかしながら,あれこれ使っているとgmtpの欠点も目についてきました。
<img border="0" width="1" height="1" src="http://rss.rssad.jp/rss/artimg/47ghQF72z411/3184e1aa6c761b751f68c2613f8a3f55"/></p>
<br clear="all" /><a href="http://rss.rssad.jp/rss/ad/47ghQF72z411/pFjyc8QFo.Eh?type=1" target="_blank"><img src="http://rss.rssad.jp/rss/img/47ghQF72z411/pFjyc8QFo.Eh?type=1" border="0"/></a><br/>

この場合HTMLをParseする必要があるため、HTMLパーサのライブラリを使い、不要な部分のみを取り除くことにします。ここから先は、次回のエントリーで。
In this case, I have to parse HTML. So I will use HTML-parsing-library. And I will remove the link of ads.
I will show you that in next post.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s