Подтвердить что ты не робот

Сегрегация фильтрованных твитов на основе совпадающих ключевых слов: Twitter4j API

Я создал твиттер-поток, отфильтрованный некоторыми ключевыми словами, следующим образом.

TwitterStream twitterStream = getTwitterStreamInstance();
FilterQuery filtre = new FilterQuery();
String[] keywordsArray = { "iphone", "samsung" , "apple", "amazon"};
filtre.track(keywordsArray);
twitterStream.filter(filtre);
twitterStream.addListener(listener);

Каков наилучший способ разделения твитов на основе совпадающих ключевых слов. например Все твиты, которые соответствуют "iphone", должны храниться в таблице "IPHONE", и все твиты, которые соответствуют "samsung", будут храниться в таблице "SAMSUNG" и так далее. ПРИМЕЧАНИЕ. Нет ключевых слов с фильтром - около 500.

4b9b3361

Ответ 1

Кажется, что единственный способ узнать, к какому ключевому слову принадлежит твит, - итерация по нескольким свойствам объекта Status. Следующий код требует службы базы данных с методом insertTweet(String tweetText, Date createdAt, String keyword), и каждый твит хранится в базе данных несколько раз, если найдено несколько ключевых слов. Если в тексте твита найдено хотя бы одно ключевое слово, дополнительные свойства не будут искать больше ключевых слов.

// creates a map of the keywords with a compiled pattern, which matches the keyword
private Map<String, Pattern> keywordsMap = new HashMap<>();
private TwitterStream twitterStream;
private DatabaseService databaseService; // implement and add this service

public void start(List<String> keywords) {
    stop(); // stop the streaming first, if it is already running

    if(keywords.size() > 0) {
        for(String keyword : keywords) {
            keywordsMap.put(keyword, Pattern.compile(keyword, Pattern.CASE_INSENSITIVE));
        }

        twitterStream = new TwitterStreamFactory().getInstance();
        StatusListener listener = new StatusListener() {
            @Override
            public void onStatus(Status status) {
                insertTweetWithKeywordIntoDatabase(status);
            }
            /* add the unimplemented methods from the interface */
        };
        twitterStream.addListener(listener);
        FilterQuery filterQuery = new FilterQuery();
        filterQuery.track(keywordsMap.keySet().toArray(new String[keywordsMap.keySet().size()]));
        filterQuery.language(new String[]{"en"});

        twitterStream.filter(filterQuery);
    }
    else {
        System.err.println("Could not start querying because there are no keywords.");
    }
}

public void stop() {
    keywordsMap.clear();
    if(twitterStream != null) {
        twitterStream.shutdown();
    }
}

private void insertTweetWithKeywordIntoDatabase(Status status) {
    // search for keywords in tweet text
    List<String> keywords = getKeywordsFromTweet(status.getText());

    if (keywords.isEmpty()) {
        StringBuffer additionalDataFromTweets = new StringBuffer();

        // get extended urls
        if (status.getURLEntities() != null) {
            for (URLEntity url : status.getURLEntities()) {
                if (url != null && url.getExpandedURL() != null) {
                    additionalDataFromTweets.append(url.getExpandedURL());
                }
            }
        }

        // get retweeted status -> text
        if (status.getRetweetedStatus() != null && status.getRetweetedStatus().getText() != null) {
            additionalDataFromTweets.append(status.getRetweetedStatus().getText());
        }
        // get retweeted status -> quoted status -> text
        if (status.getRetweetedStatus() != null && status.getRetweetedStatus().getQuotedStatus() != null
                && status.getRetweetedStatus().getQuotedStatus().getText() != null) {
            additionalDataFromTweets.append(status.getRetweetedStatus().getQuotedStatus().getText());
        }
        // get retweeted status -> quoted status -> extended urls
        if (status.getRetweetedStatus() != null && status.getRetweetedStatus().getQuotedStatus() != null
                && status.getRetweetedStatus().getQuotedStatus().getURLEntities() != null) {
            for (URLEntity url : status.getRetweetedStatus().getQuotedStatus().getURLEntities()) {
                if (url != null && url.getExpandedURL() != null) {
                    additionalDataFromTweets.append(url.getExpandedURL());
                }
            }
        }

        // get quoted status -> text
        if (status.getQuotedStatus() != null && status.getQuotedStatus().getText() != null) {
            additionalDataFromTweets.append(status.getQuotedStatus().getText());
        }
        // get quoted status -> extended urls
        if (status.getQuotedStatus() != null && status.getQuotedStatus().getURLEntities() != null) {
            for (URLEntity url : status.getQuotedStatus().getURLEntities()) {
                if (url != null && url.getExpandedURL() != null) {
                    additionalDataFromTweets.append(url.getExpandedURL());
                }
            }
        }

        String additionalData = additionalDataFromTweets.toString();
        keywords = getKeywordsFromTweet(additionalData);
    }

    if (keywords.isEmpty()) {
        System.err.println("ERROR: No Keyword found for: " + status.toString());

    } else {
        // insert into database
        for(String keyword : keywords) {
            databaseService.insertTweet(status.getText(), status.getCreatedAt(), keyword);
        }
    }

}

// returns a list of keywords which are found in a tweet
private List<String> getKeywordsFromTweet(String tweet) {
    List<String> result = new ArrayList<>();

    for (String keyword : keywordsMap.keySet()) {
        Pattern p = keywordsMap.get(keyword);
        if (p.matcher(tweet).find()) {
            result.add(keyword);
        }
    }

    return result;
}

Ответ 2

Здесь вы можете использовать StatusListener для опроса полученных Status объектов:

final Set<String> keywords = new HashSet<String>();
keywords.add("apple");
keywords.add("samsung");
// ...

final StatusListener listener = new StatusAdapter() {
    @Override
    public void onStatus(Status status) {
        final String statusText = status.getText();
        for (String keyword : keywords) {
            if (statusText.contains(keyword)) {
                dao.insert(keyword, statusText);
            }
        }
    }
};

final TwitterStream twitterStream = getTwitterStreamInstance();
final FilterQuery fq = new FilterQuery();
fq.track(keywords.toArray(new String[0]));
twitterStream.addListener(listener);
twitterStream.filter(fq);

Я вижу, что DAO определяется по строкам:

public interface StatusDao {
    void insert(String tableSuffix, Status status);
}

Тогда у вас будет таблица DB, соответствующая каждому ключевому слову. Реализация будет использовать tableSuffix для хранения Status в правильной таблице, sql будет выглядеть примерно так:

INSERT INTO status_$tableSuffix$ VALUES (...)

Примечания:

  • Эта реализация будет вставлять Status в несколько таблиц, если в твиттере содержатся "apple" и "samsung", например.

  • Кроме того, это довольно наивная реализация, вы можете захотеть рассмотреть пакетные вставки в таблицы... но это зависит от объема твитов, которые вы будете получать.

  • Как отмечено в комментариях, API рассматривает другие атрибуты при сопоставлении, например. URL и встроенный твит (если есть), поэтому поиск текста состояния для соответствия ключевому слову может быть недостаточным.

Ответ 3

Ну, вы можете создать класс, похожий на ArrayList, но сделать так, чтобы вы могли создать массив ArrayLists, назовите его TweetList. Для этого класса потребуется функция вставки.

Затем используйте два цикла для поиска по твитам и найдите подходящие ключевые слова, которые содержатся в списке обычных массивов, а затем добавьте их в TweetList, который соответствует индексу ключевого слова в ключевых словах ArrayList

 for (int i = 0; i < tweets.length; i++)
           {
               String[] split = tweets[i].split(" ");// split the tweet up
               for (int j = 0; j < split.length; j++)
                   if (keywords.contains(split[j]))//check each word against the keyword list
                       list[keywords.indexOf(j)].insert[tweets[i]];//add the tweet to the tree index that matches index of the keyword
           }