LoginSignup
2
0

More than 5 years have passed since last update.

twitter4j java 検索したツイートをDB(MySQL)に格納する。

Last updated at Posted at 2018-12-06

あるワードについて、過去分(Max8,9日分くらい)取れるだけ取得して、DB(mysql)に格納していくソース。

開発環境

  Eclipse 4.8
  jdk 1.8

APIを叩くインターバル

 MAX100件/1APIを、3秒間隔で叩きに行く。
 1インスタンスで15回叩け、その後10秒待つ。
 API上限に達すると、エラーコード429が返るので、その場合は、60秒待つ。

リソースクラス SearchWordResource

package CollectionTweet;


import java.util.Date;

import twitter4j.Status;
import twitter4j.TwitterException;
/**
 * 任意のワードを検索し、過去分のツイートをDBに格納するResourceクラス
 */
public class SearchWordResource {

    public static void main(String[] args) {

        // 無限ループ
        for (;;) {

            TrendSearch trendSearchPRG = new TrendSearch();

                WordSearch wordSearchPRG = new WordSearch();
                Status retweetStatus = null;

                try {
                    // 検索し、DBへ格納
                    String wordSearch = "働き方改革";
                    retweetStatus = wordSearchPRG.wordSearch(wordSearch);

                } catch (TwitterException e) {
                    e.printStackTrace();
                }

            // sleep
            try {
                Date date = new Date();
                System.out.println(date.toString());
                Thread.sleep(TwitterContents.TIME_INTERVAL);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

ワード検索クラス WordSearch

package CollectionTweet;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import twitter4j.Query;
import twitter4j.QueryResult;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;

/**
 * 特定ワードを検索するクラス 
 */
public class WordSearch {

    public Status wordSearch(String seachWord) throws TwitterException {

        // 初期化
        Twitter twitter = new TwitterFactory().getInstance();
        Query query = new Query();
        // 1度のリクエストで取得するTweetの数(100が最大)
        query.setCount(TwitterContents.MAX_GETTWEET_NUMBER);
        // 検索ワードをセット
        query.setQuery(seachWord);

        // DB接続
        ConnectionDB connectionDB = new ConnectionDB();
        Connection connection = null;
        Statement statement = null;
        try {
            connection = connectionDB.getConnection();
            statement = connection.createStatement();
        } catch (ClassNotFoundException | SQLException e3) {
            e3.printStackTrace();
        }

        String getMaxIdSQL = "select min(tweet_id) as min_tweet_id from t_tweet where search_word  =?;";

        List<String>  minUntilCreateDatetimeList = new ArrayList<String>();

        // DBより、検索ワードのツイート作成日時の最小値を取得
        try(
            PreparedStatement ps = connection.prepareStatement(getMaxIdSQL)){

            ps.setString(1,seachWord);

            try(ResultSet rs = ps.executeQuery()){
                while (rs.next()) {
                    System.out.println("◆◆DB格納済 ツイートIDの最小値:" + rs.getString("min_tweet_id") + "◆◆");
                    minUntilCreateDatetimeList.add(rs.getString("min_tweet_id"));
                }
            };

        } catch (SQLException e2) {
            e2.printStackTrace();
        }

        // 過去にDBに登録済の場合は、クエリ検索条件に、最小ツイートIDを指定
        if(minUntilCreateDatetimeList.get(0) != null) {

            // 指定ツイートIDより前のツイートIDを取得
            query.setMaxId(Long.valueOf(minUntilCreateDatetimeList.get(0)));
            System.out.println(minUntilCreateDatetimeList.get(0) + "_JST");
        }

        // もっともリツイート数の多いツイート
        Status popularTweet = null;

        // 検索結果
        QueryResult result = null;

        // API残基
        GetAPIRestCount getAPIRestCount = new GetAPIRestCount();

        // 検索実行
        for (int i = 0; i < TwitterContents.SERACH_PAGE_NUMBER; i++) {

            // 検索実行
            try {
                result = twitter.search(query);
                System.out.println("ヒット数 : " + result.getTweets().size());
                System.out.println("ページ数 : " + i);
            } catch (TwitterException twi_e) {
                twi_e.printStackTrace();
                if (twi_e.getStatusCode() == 429) {
                    intarvalTime();
                }
                break;
            } catch (Exception ee) {
                ee.printStackTrace();
                break;
            }

            // 取得結果が0件の場合は、nullを返す
            if(result.getTweets().size() == 0) {
                return null;
            }

            // APIをたたくインターバル:3秒
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }

            // 検索結果を見てみる
            for (Status tweet : result.getTweets()) {

                popularTweet = tweet;
//                System.out.println("◆◆◆◆◆◆検索したトレンドワード:" + seachWord + "◆◆◆◆◆◆");
                //System.out.println("ステータスID:" + popularTweet.getId()); // リツイートのときに必要
                //System.out.println("本文:" + popularTweet.getText());
                // 発言したユーザ
//                System.out.println("ユーザID_num:" + popularTweet.getUser().getId());
//                System.out.println("ユーザID@:" + popularTweet.getUser().getScreenName());
                System.out.println("ユーザ名表記:" + popularTweet.getUser().getName());
                // 発言した日時
//                System.out.println("ツイート日時:" + popularTweet.getCreatedAt());
//                System.out.println("言語:" + popularTweet.getLang());
//                System.out.println("地域:" + popularTweet.getGeoLocation());
//                System.out.println("お気に入られ数:" + popularTweet.getFavoriteCount());
//                System.out.println("リツイート数:" + popularTweet.getRetweetCount());

                // insert実行
                try {

                    String sql = "INSERT INTO T_tweet VALUES ("
                    + "'" +  popularTweet.getId()  + "'" +  "," // ツイートID これでリツイート可能
                    + "'" + popularTweet.getUser().getScreenName() + "'" + "," // ユーザID
                    + "'" + popularTweet.getUser().getName() + "'" + "," // ユーザ名
                    + "'" + popularTweet.getText() + "'" + "," // ツイート本文
                    + "'" + popularTweet.getGeoLocation() + "'" + "," // 地域
                    + "'" + popularTweet.getLang() + "'" + "," // 言語
                    + "'" + seachWord + "'" + "," // 検索ワード
                    + popularTweet.getFavoriteCount() + "," // お気に入り数
                    + popularTweet.getRetweetCount() + "," // リツイート数
                    + "'" + new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(popularTweet.getCreatedAt()) + "'"   // ツイート日時
                    + ");";

                    int resultInsert = statement.executeUpdate(sql);
                    System.out.println("結果1:" + resultInsert);

                } catch (SQLException e) {
                    e.printStackTrace();
                }
                query = result.nextQuery(); // 次ページ参照
            }
        }

        // 検索した結果、該当ツイートがない場合は、NULLを返す
        if(popularTweet == null ){
            return null;
        }

        return popularTweet;
    }

   // タイム
    public void intarvalTime() {
        Date date = new Date();
        System.out.println(date.toString());
        try {
            // 60秒
            Thread.sleep(60000);
        } catch (InterruptedException e) {
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        }
    }
}

DB接続クラス ConnectionDB

package CollectionTweet;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionDB {

    public Connection getConnection() throws ClassNotFoundException {

        Class.forName("com.mysql.cj.jdbc.Driver");

        try {

            Connection connection = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/twitter?serverTimezone=JST", "user", "password");

                        return connection;
                    } catch (SQLException ex) {
                        ex.printStackTrace();
                    }
        return null;
        }
}

API残基 GetAPIRestCount

package CollectionTweet;

import java.util.HashMap;
import java.util.Map;

import twitter4j.RateLimitStatus;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;

/**
 * API制限情報を取得 
 *
 */
public class GetAPIRestCount {

    public static void getAPIRestCount() {

        Twitter twitter = new TwitterFactory().getInstance();

        Map<String , RateLimitStatus> helpmap = new HashMap<String,RateLimitStatus>();// API制限情報を格納変数を作成
        try {
            helpmap = twitter.help().getRateLimitStatus();


                for(Map.Entry<String, RateLimitStatus> e : helpmap.entrySet()){

                    if(e.getKey().equals("/application/rate_limit_status") ||
                       e.getKey().equals("/statuses/retweeters/ids") ||
                       e.getKey().equals("/search/tweets") ||
                       e.getKey().equals("/friendships/show")){
                        System.out.println(e.getKey() + "\nremain: " + e.getValue().getRemaining());
                    }
                }
        } catch (TwitterException e1) {
            e1.printStackTrace();
        }
    }
}

定数クラス TwitterContents


package CollectionTweet;

/**
 * 定数を管理するクラス
 */
public class TwitterContents {

        // privateコンストラクタでインスタンス生成を抑止
        private TwitterContents(){};
        // 検索するトレンドワード数
        public static final int TRENDWORD_NUMBER = 2;
        // 最低リツイート数
        public static final int MIN_RETWEET_NUMBER = 150;
        // 最低リツイート数
        public static final int LOCALNUMBER_JAPAN = 23424856;
        // 処理間隔タイム
        public static final int TIME_INTERVAL = 10000;
        // リクエストで取得するTweetの数(100が最大)
        public static final int MAX_GETTWEET_NUMBER = 100;
        // 検索するページ数 max 15ページ
        public static final int SERACH_PAGE_NUMBER = 15;
    }

DDL

CREATE TABLE `t_tweet` (
  `tweet_id` varchar(256) NOT NULL,
  `user_id` varchar(256) NOT NULL,
  `user_name` varchar(256) DEFAULT NULL,
  `tweet` text,
  `location` varchar(256) DEFAULT NULL,
  `langeuge` varchar(256) DEFAULT NULL,
  `search_word` varchar(256) NOT NULL,
  `favarite_count` bigint(20) DEFAULT NULL,
  `retweet_count` bigint(20) DEFAULT NULL,
  `create_datetime` datetime DEFAULT NULL,
  PRIMARY KEY (`tweet_id`,`user_id`,`search_word`),
  UNIQUE KEY `tweet_id_UNIQUE` (`tweet_id`,`user_id`,`search_word`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0