twitter4j因为id没有得到更新

时间:2016-07-21 00:59:48

标签: scala twitter twitter4j

我正在尝试使用since_id来使用twitter搜索API来获取推文。下面是我的代码,这里我创建了一个查询对象的地图,因为我是id。我将自从id默认为0,我的目标是每次运行查询时更新自身ID。因此,当下次我要运行查询时,它不会得到相同的推文,应该从最后一条推文开始。

import java.io.{PrintWriter, StringWriter}
import java.util.Properties
import com.google.common.io.Resources
import twitter4j._
import scala.collection.JavaConversions._
// reference: http://bcomposes.com/2013/02/09/using-twitter4j-with-scala-to-access-streaming-tweets/
object Util {
    val props = Resources.getResource("twitter4j.props").openStream()
    val properties = new Properties()
    properties.load(props)

    val config = new twitter4j.conf.ConfigurationBuilder()
        .setDebugEnabled(properties.getProperty("debug").toBoolean)
        .setOAuthConsumerKey(properties.getProperty("consumerKey"))
        .setOAuthConsumerSecret(properties.getProperty("consumerSecret"))
        .setOAuthAccessToken(properties.getProperty("accessToken"))
        .setOAuthAccessTokenSecret(properties.getProperty("accessTokenSecret"))
    val tempKeys =List("Yahoo","Bloomberg","Messi", "JPM Chase","Facebook")
    val sinceIDmap : scala.collection.mutable.Map[String, Long] = collection.mutable.Map(tempKeys map { ix => s"$ix" -> 0.toLong } : _*)
    //val tweetsMap: scala.collection.mutable.Map[String, String]
    val configBuild = (config.build())
    val MAX_TWEET=100
    getTweets()

    def getTweets(): Unit ={
        sinceIDmap.keys.foreach((TickerId) => getTweets(TickerId))
    }

    def getTweets(TickerId: String): scala.collection.mutable.Map[String, scala.collection.mutable.Buffer[String]] = {
        println("Search key is:"+TickerId)
        var tweets = scala.collection.mutable.Map[String, scala.collection.mutable.Buffer[String]]()
        try {
            val twitter: Twitter = new TwitterFactory(configBuild).getInstance
            val query = new Query(TickerId)
            query.setSinceId(sinceIDmap.get(TickerId).get)
            query.setLang("en")
            query.setCount(MAX_TWEET)
            val result = twitter.search(query)
            tweets += ( TickerId -> result.getTweets().map(_.getText))

            //sinceIDmap(TickerId)=result.getSinceId
            println("-----------Since id is :"+result.getSinceId )
            //println(tweets)
        }
        catch {
            case te: TwitterException =>
                println("Failed to search tweets: " + te.getMessage)
        }
        tweets
    }
}

object StatusStreamer {
    def main(args: Array[String]) {
        Util
    }
}

输出:

Search key is:Yahoo    
log4j:WARN No appenders could be found for logger (twitter4j.HttpClientImpl).
log4j:WARN Please initialize the log4j system properly.
-----------Since id is :0
Search key is:JPM Chase
-----------Since id is :0
Search key is:Facebook
-----------Since id is :0
Search key is:Bloomberg
-----------Since id is :0
Search key is:Messi
-----------Since id is :0

问题是当我在运行查询后尝试打印自身ID后,它给出了我最初设置的相同值。有人能指出我在这里做错了吗?或者如果我的方法有误,可以有人分享任何其他方法,如果他们知道可以在这里工作。

由于

4 个答案:

答案 0 :(得分:4)

Twitter API返回查询最初请求的since_id值。这意味着QueryResult.getSinceIdQuery中的sinceId相同。

最简单的解决方案是将下一个sinceIDmap(TickerId) = result.getTweets().max(Ordering.by(_.getId)).getId 设置为响应的最大推文ID。

since_id

通常,为了使结果更加流畅,您可以使用max_id<?php $UserAgent = $_SERVER['HTTP_USER_AGENT']; echo "$UserAgent"; ?> 查询参数的组合。 Official twitter guide非常好地解释了如何使用它们。

答案 1 :(得分:4)

首先,从您对方法的初步描述中,我可以告诉您,使用since_id的方法不正确。我过去犯了同样的错误,无法让它发挥作用。此外,您的方法与官方Working with Timelines不一致。官方指南对我有用,我建议你遵循它们。简而言之,您无法单独使用since_id来浏览推文的时间轴(GET search / tweets返回的时间轴,在您的情况下)。你肯定需要max_id来做你描述的事情。而且,实际上,我认为since_id具有完全辅助/可选功能(也可以在您的代码中实现)。 API docs让我相信我可以使用since_id,就像使用max_id一样,但我错了。仅指定since_id,我注意到返回的推文非常新鲜,好像since_id被完全忽略了。 Here是另一个证明这种意外行为的问题。在我看来,since_id仅用于修剪,而不是用于在时间轴中移动。单独使用since_id将获得最新/最新的推文,但限制返回到ID大于since_id的推文。不是你想要的。从官方指南中得出的最后一个证据是特定请求的图形表示:

since_id

since_id不仅没有让您完成时间线,而且在此特定请求中恰好无用。但是,在下一个请求中它不会没用,因为它会修剪Tweet 10(以及之前的任何内容)。但事实是since_id并没有让你完成时间表。

一般来说,你需要考虑从最新的推文到最古老的推文,而不是相反。从最新的推文到最早的推文,在您的请求中,您需要指定max_id作为返回推文的ID包含上限,并在连续请求之间更新此参数。

请求中max_id的存在将设置返回推文的ID包含上限。从返回的推文中,您可以获得出现的最小ID,并将其用作后续请求中max_id的值(您可以将最小ID减1,并将此值用于下一个请求&#39; s { {1}},因为max_id具有包容性,因此您不会再次获得上一个请求中最早的推文)。第一个请求应该没有指定max_id,以便返回最新/最新的推文。使用这种方法,第一次请求后的每个请求都会让您更深入地了解过去。

当你需要限制你的旅行时,

max_id可以派上用场。想象一下,在某个时间点since_id,您开始搜索推文。我们假设您的第一次搜索时最大的推文ID是t0。在第一次搜索之后,后续搜索中的所有推文ID将变得越来越小,因为您要回去了。过了一段时间,你将得到大约一个星期的推文,而你的搜索将不会返回任何内容。在那个时间点,id0,你知道这次过去的旅程结束了。但是,在t1t0之间,推文会发送更多推文。因此,过去的另一次旅行应该从t1开始,直到您收到ID为t1的推文(在id0之前发过推文)。在旅行的请求中使用t0 id0可以限制此行程,依此类推。或者,可以避免使用since_id,如果您确定一旦您的推文的ID小于或等于since_id,您的行程就会结束(请记住推文)可以删除)。但我建议你尝试使用id0来提高效率。请记住,since_id是独占的,since_id是包容性的。

有关详细信息,请参阅官方Working with Timelines。你会注意到&#34; max_id参数&#34;第一部分和第34部分使用since_id以获得最高效率&#34;来晚了。后一部分的标题表示max_id 在时间轴中移动。

一个粗略的未经测试的例子,使用Java中的Twitter4J打印从最新到过去的推文如下:

since_id

没有错误处理,没有特殊条件检查(例如查询结果中的推文空列表),也没有使用// Make sure this is initialized correctly. Twitter twitter; /** * Searches and prints tweets starting from now and going back to the past. * * @param q * the search query, e.g. "#yolo" */ private void searchAndPrintTweets(String q) throws TwitterException { // `max_id` needed by `GET search/tweets`. If it is 0 (first iteration), // it will not be used for the query. long maxId = 0; // Let us assume that it will run forever. while (true) { Query query = new Query(); query.setCount(100); query.setLang("en"); // Set `max_id` as an inclusive upper limit, unless this is the // first iteration. If this is the first iteration (maxId == 0), the // freshest/latest tweets will come. if (maxId != 0) query.setMaxId(maxId); QueryResult qr = twitter.search(query); printTweets(qr.getTweets()); // For next iteration. Decrement smallest ID by 1, so that we will // not get the oldest tweet of this iteration in the next iteration // as well, since `max_id` is inclusive. maxId = calculateSmallestId(qr.getTweets()) - 1; } } /** * Calculates the smallest ID among a list of tweets. * * @param tweets * the list of tweets * @return the smallest ID */ private long calculateSmallestId(List<Status> tweets) { long smallestId = Long.MAX_VALUE; for (Status tweet : tweets) { if (tweet.getId() < smallestId) smallestId = tweet.getId(); } return smallestId; } /** * Prints the content of the tweets. * * @param tweets * the tweets */ private void printTweets(List<Status> tweets) { for (Status tweet : tweets) { System.out.println(tweet.getText()); } } ,但它应该让你开始。

答案 2 :(得分:3)

通过粗略查看代码,您似乎永远不会更新sinceIDmap中的值。您已注释掉以下内容:

//sinceIDmap(TickerId)=result.getSinceId

因此,对于每个关键字,since_id永远不会从0更新。

如果您遇到问题,可能需要检查GitHub上的Twitter4J SearchTweets示例。

答案 3 :(得分:1)

since_id和max_id都是非常简单的参数,可以用来限制从API返回的内容。来自文档:

since_id - 返回ID大于(即更新)指定ID的结果。可以通过API访问的推文数量有限制。如果自since_id以来发生了推文限制,则since_id将被强制为可用的最旧ID。 max_id - 返回ID小于(即早于)或等于指定ID的结果。 因此,如果您有一个特定的推文ID,您可以使用这两个参数搜索较旧或较新的推文。

计数甚至更简单 - 它指定了您想要获得的最大推文数量,最多可达200​​个。

不幸的是,API不会完全回复您所需的内容 - 您无法在查询user_timeline时指定日期/时间 - 尽管您可以在使用搜索API时指定一个日期/时间。无论如何,如果您需要使用user_timeline,那么您需要轮询API,收集推文,确定它们是否与您想要的参数相匹配,然后相应地计算您的统计数据。