由于Twitter API 1.0于2013年6月11日退休,下面的脚本不再工作。

// Create curl resource 
$ch = curl_init(); 
// Set url 
curl_setopt($ch, CURLOPT_URL, "http://twitter.com/statuses/user_timeline/myscreenname.json?count=10"); 
// Return the transfer as a string 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
// $output contains the output string 
$output = curl_exec($ch); 
// Close curl resource to free up system resources 
curl_close($ch);

if ($output) 
{
    $tweets = json_decode($output,true);

    foreach ($tweets as $tweet)
    {
        print_r($tweet);
    }
}

如何用最少的代码获得user_timeline(最近的状态)?

我找到了这个:https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline 但是我得到了以下错误:

"{"errors":[{"message":"Could not authenticate you","code":32}]}"

有很多课程,但在尝试了几个之后,它们似乎都没有工作,因为Twitter上的这些更新,加上其中一些是非常高级的课程,有很多功能,我真的不需要。

用PHP获取最近用户状态的最简单/最短的方法是什么?


当前回答

这个问题对我帮助很大,但并没有让我完全理解需要发生什么。这篇博客文章很好地引导了我。

以下是所有重要的部分:

As pointed out above, you MUST sign your 1.1 API requests. If you are doing something like getting public statuses, you'll want an application key rather than a user key. The full link to the page you want is: https://dev.twitter.com/apps You must hash ALL the parameters, both the oauth ones AND the get parameters (or POST parameters) together. You must SORT the parameters before reducing them to the url encoded form that gets hashed. You must encode some things multiple times - for example, you create a query string from the parameters' url-encoded values, and then you url encode THAT and concatenate with the method type and the url.

我同情所有这些令人头痛的问题,所以这里有一些代码来总结:

$token = 'YOUR TOKEN';
$token_secret = 'TOKEN SECRET';
$consumer_key = 'YOUR KEY';
$consumer_secret = 'KEY SECRET';

$host = 'api.twitter.com';
$method = 'GET';
$path = '/1.1/statuses/user_timeline.json'; // api call path

$query = array( // query parameters
    'screen_name' => 'twitterapi',
    'count' => '2'
);

$oauth = array(
    'oauth_consumer_key' => $consumer_key,
    'oauth_token' => $token,
    'oauth_nonce' => (string)mt_rand(), // a stronger nonce is recommended
    'oauth_timestamp' => time(),
    'oauth_signature_method' => 'HMAC-SHA1',
    'oauth_version' => '1.0'
);

$oauth = array_map("rawurlencode", $oauth); // must be encoded before sorting
$query = array_map("rawurlencode", $query);

$arr = array_merge($oauth, $query); // combine the values THEN sort

asort($arr); // secondary sort (value)
ksort($arr); // primary sort (key)

// http_build_query automatically encodes, but our parameters
// are already encoded, and must be by this point, so we undo
// the encoding step
$querystring = urldecode(http_build_query($arr, '', '&'));

$url = "https://$host$path";

// mash everything together for the text to hash
$base_string = $method."&".rawurlencode($url)."&".rawurlencode($querystring);

// same with the key
$key = rawurlencode($consumer_secret)."&".rawurlencode($token_secret);

// generate the hash
$signature = rawurlencode(base64_encode(hash_hmac('sha1', $base_string, $key, true)));

// this time we're using a normal GET query, and we're only encoding the query params
// (without the oauth params)
$url .= "?".http_build_query($query);

$oauth['oauth_signature'] = $signature; // don't want to abandon all that work!
ksort($oauth); // probably not necessary, but twitter's demo does it

// also not necessary, but twitter's demo does this too
function add_quotes($str) { return '"'.$str.'"'; }
$oauth = array_map("add_quotes", $oauth);

// this is the full value of the Authorization line
$auth = "OAuth " . urldecode(http_build_query($oauth, '', ', '));

// if you're doing post, you need to skip the GET building above
// and instead supply query parameters to CURLOPT_POSTFIELDS
$options = array( CURLOPT_HTTPHEADER => array("Authorization: $auth"),
                  //CURLOPT_POSTFIELDS => $postfields,
                  CURLOPT_HEADER => false,
                  CURLOPT_URL => $url,
                  CURLOPT_RETURNTRANSFER => true,
                  CURLOPT_SSL_VERIFYPEER => false);

// do our business
$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);

$twitter_data = json_decode($json);

其他回答

如果安装了OAuth PHP库,就不必担心自己生成请求。

$oauth = new OAuth($consumer_key, $consumer_secret, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
$oauth->setToken($access_token, $access_secret);

$oauth->fetch("https://api.twitter.com/1.1/statuses/user_timeline.json");
$twitter_data = json_decode($oauth->getLastResponse());

print_r($twitter_data);

有关更多信息,请查看文档或它们的示例。您可以使用pecl install oauth来获取库。

这个问题对我帮助很大,但并没有让我完全理解需要发生什么。这篇博客文章很好地引导了我。

以下是所有重要的部分:

As pointed out above, you MUST sign your 1.1 API requests. If you are doing something like getting public statuses, you'll want an application key rather than a user key. The full link to the page you want is: https://dev.twitter.com/apps You must hash ALL the parameters, both the oauth ones AND the get parameters (or POST parameters) together. You must SORT the parameters before reducing them to the url encoded form that gets hashed. You must encode some things multiple times - for example, you create a query string from the parameters' url-encoded values, and then you url encode THAT and concatenate with the method type and the url.

我同情所有这些令人头痛的问题,所以这里有一些代码来总结:

$token = 'YOUR TOKEN';
$token_secret = 'TOKEN SECRET';
$consumer_key = 'YOUR KEY';
$consumer_secret = 'KEY SECRET';

$host = 'api.twitter.com';
$method = 'GET';
$path = '/1.1/statuses/user_timeline.json'; // api call path

$query = array( // query parameters
    'screen_name' => 'twitterapi',
    'count' => '2'
);

$oauth = array(
    'oauth_consumer_key' => $consumer_key,
    'oauth_token' => $token,
    'oauth_nonce' => (string)mt_rand(), // a stronger nonce is recommended
    'oauth_timestamp' => time(),
    'oauth_signature_method' => 'HMAC-SHA1',
    'oauth_version' => '1.0'
);

$oauth = array_map("rawurlencode", $oauth); // must be encoded before sorting
$query = array_map("rawurlencode", $query);

$arr = array_merge($oauth, $query); // combine the values THEN sort

asort($arr); // secondary sort (value)
ksort($arr); // primary sort (key)

// http_build_query automatically encodes, but our parameters
// are already encoded, and must be by this point, so we undo
// the encoding step
$querystring = urldecode(http_build_query($arr, '', '&'));

$url = "https://$host$path";

// mash everything together for the text to hash
$base_string = $method."&".rawurlencode($url)."&".rawurlencode($querystring);

// same with the key
$key = rawurlencode($consumer_secret)."&".rawurlencode($token_secret);

// generate the hash
$signature = rawurlencode(base64_encode(hash_hmac('sha1', $base_string, $key, true)));

// this time we're using a normal GET query, and we're only encoding the query params
// (without the oauth params)
$url .= "?".http_build_query($query);

$oauth['oauth_signature'] = $signature; // don't want to abandon all that work!
ksort($oauth); // probably not necessary, but twitter's demo does it

// also not necessary, but twitter's demo does this too
function add_quotes($str) { return '"'.$str.'"'; }
$oauth = array_map("add_quotes", $oauth);

// this is the full value of the Authorization line
$auth = "OAuth " . urldecode(http_build_query($oauth, '', ', '));

// if you're doing post, you need to skip the GET building above
// and instead supply query parameters to CURLOPT_POSTFIELDS
$options = array( CURLOPT_HTTPHEADER => array("Authorization: $auth"),
                  //CURLOPT_POSTFIELDS => $postfields,
                  CURLOPT_HEADER => false,
                  CURLOPT_URL => $url,
                  CURLOPT_RETURNTRANSFER => true,
                  CURLOPT_SSL_VERIFYPEER => false);

// do our business
$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);

$twitter_data = json_decode($json);

感谢这个帖子,尤其是budidino,因为他的代码让我明白了这一点。 只是想贡献一下如何从请求中检索JSON数据。 更改“//create request”请求数组部分的代码以执行不同的请求。最终,这将把JSON输出到浏览器屏幕上

<?php
    function buildBaseString($baseURI, $method, $params) {
    $r = array();
    ksort($params);
    foreach($params as $key=>$value){
        $r[] = "$key=" . rawurlencode($value);
    }
    return $method."&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));
}

function buildAuthorizationHeader($oauth) {
    $r = 'Authorization: OAuth ';
    $values = array();
    foreach($oauth as $key=>$value)
        $values[] = "$key=\"" . rawurlencode($value) . "\"";
    $r .= implode(', ', $values);
    return $r;
}

function returnTweet(){
    $oauth_access_token         = "2602299919-lP6mgkqAMVwvHM1L0Cplw8idxJzvuZoQRzyMkOx";
    $oauth_access_token_secret  = "wGWny2kz67hGdnLe3Uuy63YZs4nIGs8wQtCU7KnOT5brS";
    $consumer_key               = "zAzJRrPOj5BvOsK5QhscKogVQ";
    $consumer_secret            = "Uag0ujVJomqPbfdoR2UAWbRYhjzgoU9jeo7qfZHCxR6a6ozcu1";

    $twitter_timeline           = "user_timeline";  //  mentions_timeline / user_timeline / home_timeline / retweets_of_me

    //  create request
        $request = array(
            'screen_name'       => 'burownrice',
            'count'             => '3'
        );

    $oauth = array(
        'oauth_consumer_key'        => $consumer_key,
        'oauth_nonce'               => time(),
        'oauth_signature_method'    => 'HMAC-SHA1',
        'oauth_token'               => $oauth_access_token,
        'oauth_timestamp'           => time(),
        'oauth_version'             => '1.0'
    );

    //  merge request and oauth to one array
        $oauth = array_merge($oauth, $request);

    //  do some magic
        $base_info              = buildBaseString("https://api.twitter.com/1.1/statuses/$twitter_timeline.json", 'GET', $oauth);
        $composite_key          = rawurlencode($consumer_secret) . '&' . rawurlencode($oauth_access_token_secret);
        $oauth_signature            = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
        $oauth['oauth_signature']   = $oauth_signature;

    //  make request
        $header = array(buildAuthorizationHeader($oauth), 'Expect:');
        $options = array( CURLOPT_HTTPHEADER => $header,
                          CURLOPT_HEADER => false,
                          CURLOPT_URL => "https://api.twitter.com/1.1/statuses/$twitter_timeline.json?". http_build_query($request),
                          CURLOPT_RETURNTRANSFER => true,
                          CURLOPT_SSL_VERIFYPEER => false);

        $feed = curl_init();
        curl_setopt_array($feed, $options);
        $json = curl_exec($feed);
        curl_close($feed);

    return $json;
}

$tweet = returnTweet();
echo $tweet;

?>

如在其他答案中所述,创建一个Twitter应用程序来获得令牌,密钥和秘密。 使用下面的代码,您可以从一个点修改请求参数,并避免拼写错误和类似的错误(在returnTweet()函数中更改$request数组)。

function buildBaseString($baseURI, $method, $params) {
    $r = array();
    ksort($params);
    foreach($params as $key=>$value){
        $r[] = "$key=" . rawurlencode($value);
    }
    return $method."&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));
}

function buildAuthorizationHeader($oauth) {
    $r = 'Authorization: OAuth ';
    $values = array();
    foreach($oauth as $key=>$value)
        $values[] = "$key=\"" . rawurlencode($value) . "\"";
    $r .= implode(', ', $values);
    return $r;
}

function returnTweet(){
    $oauth_access_token         = "x";
    $oauth_access_token_secret  = "x";
    $consumer_key               = "x";
    $consumer_secret            = "x";

    $twitter_timeline           = "user_timeline";  //  mentions_timeline / user_timeline / home_timeline / retweets_of_me

    //  create request
        $request = array(
            'screen_name'       => 'budidino',
            'count'             => '3'
        );

    $oauth = array(
        'oauth_consumer_key'        => $consumer_key,
        'oauth_nonce'               => time(),
        'oauth_signature_method'    => 'HMAC-SHA1',
        'oauth_token'               => $oauth_access_token,
        'oauth_timestamp'           => time(),
        'oauth_version'             => '1.0'
    );

    //  merge request and oauth to one array
        $oauth = array_merge($oauth, $request);

    //  do some magic
        $base_info              = buildBaseString("https://api.twitter.com/1.1/statuses/$twitter_timeline.json", 'GET', $oauth);
        $composite_key          = rawurlencode($consumer_secret) . '&' . rawurlencode($oauth_access_token_secret);
        $oauth_signature            = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
        $oauth['oauth_signature']   = $oauth_signature;

    //  make request
        $header = array(buildAuthorizationHeader($oauth), 'Expect:');
        $options = array( CURLOPT_HTTPHEADER => $header,
                          CURLOPT_HEADER => false,
                          CURLOPT_URL => "https://api.twitter.com/1.1/statuses/$twitter_timeline.json?". http_build_query($request),
                          CURLOPT_RETURNTRANSFER => true,
                          CURLOPT_SSL_VERIFYPEER => false);

        $feed = curl_init();
        curl_setopt_array($feed, $options);
        $json = curl_exec($feed);
        curl_close($feed);

    return json_decode($json, true);
}

然后调用returnTweet()

如果对任何人有用的话…… 在我的博客中,我实现了下面的PHP代码,以便检索最近的tweet,提取最相关的数据,然后将它们保存到MySQL数据库中。 因为我在博客里看到了。

存储它们的“tweets”表:

CREATE TABLE IF NOT EXISTS `tweets` (
  `tweet_id` int(11) NOT NULL auto_increment,
  `id_tweet` bigint(20) NOT NULL,
  `text_tweet` char(144) NOT NULL,
  `datetime_tweet` datetime NOT NULL,
  `dayofweek_tweet` char(3) NOT NULL,
  `GMT_tweet` char(5) NOT NULL,
  `shorturl_tweet` char(23) NOT NULL,
  PRIMARY KEY  (`tweet_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=83 ;

get_tweets.php:

<?php
function buildBaseString($baseURI, $method, $params) {
    $r= array();
    ksort($params);
    foreach($params as $key=>$value){
        $r[]= "$key=".rawurlencode($value);
    }
    return $method."&".rawurlencode($baseURI).'&'.rawurlencode(implode('&', $r));
}

function buildAuthorizationHeader($oauth) {
    $r= 'Authorization: OAuth ';
    $values= array();
    foreach($oauth as $key=>$value) {
        $values[]= "$key=\"".rawurlencode($value)."\"";
    }
    $r.= implode(', ', $values);
    return $r;
}

function returnTweets($last_id) {
    $oauth_access_token         = "2687912757-vbyfJA483SEyj2HJ2K346aVMxtOIgVbsY4Edrsw";
    $oauth_access_token_secret  = "nIruzmR0bXqC3has4fTf8KAq4pgOceiuKqjklhroENU4W";
    $api_key                    = "ieDSTFH8QHHPafg7H0whQB9GaY";
    $api_secret                 = "mgm8wVS9YP93IJmTQtsmR8ZJADDNdlTca5kCizMkC7O7gFDS1j";
    $twitter_timeline           = "user_timeline";  //[mentions_timeline/user_timeline/home_timeline/retweets_of_me]
    //create request
    $request= array(
        'screen_name'       => 'runs_ES',
        'count'             => '3',
        'exclude_replies'   => 'true'
        );
    if (!is_null($last_id)) { //Add to the request if it exits a last_id
        $request['since_id']= $max_id;
    }
    $oauth = array(
        'oauth_consumer_key'        => $api_key,
        'oauth_nonce'               => time(),
        'oauth_signature_method'    => 'HMAC-SHA1',
        'oauth_token'               => $oauth_access_token,
        'oauth_timestamp'           => time(),
        'oauth_version'             => '1.0'
        );
    //merge request and oauth to one array
    $oauth= array_merge($oauth, $request);
    //do some magic
    $base_info=                 buildBaseString("https://api.twitter.com/1.1/statuses/$twitter_timeline.json", 'GET', $oauth);
    $composite_key=             rawurlencode($api_secret).'&'.rawurlencode($oauth_access_token_secret);
    $oauth_signature=           base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
    $oauth['oauth_signature']=  $oauth_signature;
    //make request
    $header= array(buildAuthorizationHeader($oauth), 'Expect:');
    $options= array(CURLOPT_HTTPHEADER => $header,
                    CURLOPT_HEADER => false,
                    CURLOPT_URL => "https://api.twitter.com/1.1/statuses/$twitter_timeline.json?". http_build_query($request),
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_SSL_VERIFYPEER => false);
    $feed= curl_init();
    curl_setopt_array($feed, $options);
    $json= curl_exec($feed);
    curl_close($feed);
    return $json;
}

function parse_tweettext($tweet_text) {
    $text= substr($tweet_text, 0, -23);
    $short_url= substr($tweet_text, -23, 23);
    return array ('text'=>$text, 'short_url'=> $short_url);
}

function parse_tweetdatetime($tweetdatetime) {
    //Thu Aug 21 21:57:26 +0000 2014 Sun Mon Tue Wed Thu Fri Sat
    $months= array('Jan'=>'01', 'Feb'=>'02', 'Mar'=>'03', 'Apr'=>'04', 'May'=>'05', 'Jun'=>'06', 
                    'Jul'=>'07', 'Aug'=>'08', 'Sep'=>'09', 'Oct'=>'10', 'Nov'=>'11', 'Dec'=>'12');
    $GMT= substr($tweetdatetime, -10, 5);
    $year= substr($tweetdatetime, -4, 4);
    $month_str= substr($tweetdatetime, 4, 3);
    $month= $months[$month_str];
    $day= substr($tweetdatetime, 8, 2); 
    $dayofweek= substr($tweetdatetime, 0, 3);
    $time= substr($tweetdatetime, 11, 8);
    $date= $year.'-'.$month.'-'.$day;
    $datetime= $date.' '.$time;
    return array('datetime'=>$datetime, 'dayofweek'=>$dayofweek, 'GMT'=>$GMT);
    //datetime: "YYYY-MM-DD HH:MM:SS", dayofweek: Mon, Tue..., GMT: +####
}

//First check in the database the last id tweet:
$query= "SELECT MAX(tweets.id_tweet) AS id_last FROM tweets;";
$result= exec_query($query);
$row= mysql_fetch_object($result);
if ($result!= 0 && mysql_num_rows($result)) { //if error in query or not results
    $last_id= $row->id_last;
}
else {
    $last_id= null;
}

$json= returnTweets($last_id);
$tweets= json_decode($json, TRUE);

foreach ($tweets as $tweet) {
    $tweet_id= $tweet['id'];
    if (!empty($tweet_id)) { //if array is not empty
        $tweet_parsetext= parse_tweettext($tweet['text']);
        $tweet_text= utf8_encode($tweet_parsetext['text']);
        $tweet_shorturl= $tweet_parsetext['short_url'];
        $tweet_parsedt= parse_tweetdatetime($tweet['created_at']);
        $tweet_datetime= $tweet_parsedt['datetime'];
        $tweet_dayofweek= $tweet_parsedt['dayofweek'];
        $tweet_GMT= $tweet_parsedt['GMT'];
        //Insert the tweet into the database:
        $fields = array(
            'id_tweet' => $tweet_id,
            'text_tweet' => $tweet_text,
            'datetime_tweet' => $tweet_datetime,
            'dayofweek_tweet' => $tweet_dayofweek,
            'GMT_tweet' => $tweet_GMT,
            'shorturl_tweet' => $tweet_shorturl
            );
        $new_id= mysql_insert('tweets', $fields);
    }
} //end of foreach
?>

保存推文功能:

function mysql_insert($table, $inserts) {
    $keys = array_keys($inserts);
    exec_query("START TRANSACTION;");
    $query= 'INSERT INTO `'.$table.'` (`'.implode('`,`', $keys).'`) VALUES (\''.implode('\',\'', $inserts).'\')';
    exec_query($query);
    $id= mysql_insert_id();
    if (mysql_error()) {
        exec_query("ROLLBACK;");
        die("Error: $query");
    }
    else {
        exec_query("COMMIT;");
    }
    return $id;
}