使用cURL输出

6
我将记录特定主题的实时推文。 为此,我使用PHP中带有cURL的twitter stream API。
以下是代码:
<?php

$username = "xxxxx";
$password = "xxxxx";


$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://stream.twitter.com/1/statuses/filter.json?         track=SEARCH_PARAMETER');
curl_setopt($ch, CURLOPT_USERPWD, $username.":".$password);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$result = curl_exec($ch);
$jsonOBJ = json_decode ($result);

curl_close($ch);

print_r($jsonOBJ);
?>

我的问题是,如果我将CURLOPT_RETURNTRANSFER设置为0,我可以在终端上看到推文。但我无法将其存储在变量$jsonOBJ中并打印出来。
请帮忙!

使用带有OAuth的PHP SDK难道不更容易吗? - chepe263
在尝试解码之前,打印出 $result 以查看其外观。 - MrCode
现在,我直接执行这个命令 "echo $result;"。 但是在执行这个脚本时没有任何显示。 - Gooner
你正在尝试解码可能达到10000或超过125MB数据的结果...你应该使用“stream”而不是curl。 - Baba
@Baba 我已经添加了 "curl_setopt($ch, CURLOPT_TIMEOUT, 30);",以便我获取有限的数据并终止cURL操作。但是变量中仍然没有存储任何数据。感谢您的建议。我会研究一下 'stream'。 - Gooner
4个回答

4
更新:请查看本消息末尾的新代码,使用 cURL 很容易实现,但我第一次的方法有误。

我无法使用CURLOPT_READFUNCTION使 Twitter 流 API 与cURL配合工作,但是使用 fsockopen()fread() 成功了。我不知道为什么 readfunction 没有起作用,因为我以前在其他地方成功过。但这可能与响应数据是“流式传输”而不是使用 HTTP 分块编码发送有关。基本上,我的读取函数从未被调用,因此无法处理数据。

我现在使用的方法:

  • 使用 fsockopen 连接到 ssl://stream.twitter.com
  • 使用fputs发出用于流数据的基本 HTTP 请求
  • 消费 HTTP 响应标头,并确保没有错误
  • 使用 fread 在一个无限循环中读取一定量的数据
  • 每当读取到一片数据时,就会调用一个内部缓冲区函数
  • 缓冲函数将新数据附加到缓冲区中
  • 然后缓冲函数尝试处理缓冲区中的所有消息(如果我们有一个或多个完整的消息)
  • 处理每个消息时,缓冲区将被减少,直到为空,然后函数返回并重新读取数据

我已经让它运行了几个小时,没有发生过断开连接的情况,且已经处理了 30,000 条消息而没有出现错误。

基本上,我实现了一个回调系统,以便每当从缓冲区中读取到完整的消息时,它都会调用用户定义的回调函数并传递json消息,这样应用程序就可以对消息执行其需要的任何操作(例如插入数据库)。

我没有简短的代码段可以在此处发布,但如果您愿意,请通过访问我的个人资料中列出的网站并填写联系表格与我联系,我很乐意分享。也许我们可以一起合作,如果有人感兴趣。我只是为了好玩而这么做,我对 Twitter 没有兴趣,并且不出于金融原因使用它。我可能最终会将它放在 GitHub 上。

编辑:

下面是一些 cURL 代码,它将连接到流 API 并在可用时将 JSON 消息传递给回调函数。此示例使用 gzip 编码以节省带宽。

<?php

$USERNAME = 'youruser';
$PASSWORD = 'yourpass';
$QUERY    = 'nike';

/**
 * Called every time a chunk of data is read, this will be a json encoded message
 * 
 * @param resource $handle The curl handle
 * @param string   $data   The data chunk (json message)
 */
function writeCallback($handle, $data)
{
    /*
    echo "-----------------------------------------------------------\n";
    echo $data;
    echo "-----------------------------------------------------------\n";
    */

    $json = json_decode($data);
    if (isset($json->user) && isset($json->text)) {
        echo "@{$json->user->screen_name}: {$json->text}\n\n";
    }

    return strlen($data);
}

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://stream.twitter.com/1/statuses/filter.json?track=' . urlencode($QUERY));
curl_setopt($ch, CURLOPT_USERPWD, "$USERNAME:$PASSWORD");
curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'writeCallback');
curl_setopt($ch, CURLOPT_TIMEOUT, 20); // disconnect after 20 seconds for testing
curl_setopt($ch, CURLOPT_VERBOSE, 1);  // debugging
curl_setopt($ch, CURLOPT_ENCODING,  'gzip, deflate'); // req'd to get gzip
curl_setopt($ch, CURLOPT_USERAGENT, 'tstreamer/1.0'); // req'd to get gzip

curl_exec($ch); // commence streaming

$info = curl_getinfo($ch);

var_dump($info);

非常感谢您的建议。 目前,我通过使用搜索Twitter API找到了一个解决方法。 当我再次使用流API时,我一定会联系您。 - Gooner
@Rubie_Newbie,我添加了一个使用cURL的流API的工作示例。我还有一个在C#中工作的版本。这个php类phirehose也可能对您感兴趣,尽管它不支持gzip。 - drew010

1

对于Reza Sanaie和其他可能会发现这个有用的人。

我使用了SEARCH TWITTER API并获取了实时推文,所以这可能会有所帮助。 以下是代码:

<?php
$query = "SEARCH_PARAMETER";
$request = "http://search.twitter.com/search.json?q=".urlencode($query);
$response = file_get_contents($request);
$jsonobj = json_decode($response);
 print_r($jsonobj);
?>

我还设置了MySQL连接以将其推送到数据库中,并将此脚本添加到crontab中以自动化整个过程。


1
我也在做同样的事情 :) 问题是,当你在终端中执行时,它是一个流,所以连接会一直保持活动状态,直到你杀死它。(即curl_exec()没有完成)
尝试查看CURLOPT_PROGRESSFUNCTION和CURLOPT_READFUNCTION。它们可能会给你一些提示。

我已经添加了“curl_setopt($ch, CURLOPT_TIMEOUT, 30);”来终止curl_exec()。但是变量中仍然没有存储数据。 - Gooner
那30秒内有推文被发出吗? - Reza S
可以。我可以通过将其打印到终端来查看它们。 - Gooner
说实话,我也在尝试解决同样的问题。问题是我们不能每30秒连接一次Twitter,否则他们会阻止我们。我们需要与他们保持长时间的连接,只要我们打算读取流。因此,它可能必须在后台运行,将其写入另一个流中,然后网页读取该第二个流...或者可能有一种更简单的方法,我还没有想到。 - Reza S

0

我只是匆忙地给你一个答案,因为今天要离开了。那看起来应该可以工作。

下面是一个函数,我会传递一个URL和一些XML数据,它会返回一个关联数组,表示成功或失败的真假值以及返回值作为字符串。

function do_curl($url, $data)
    {
    $ch = curl_init();    
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, 1); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    $result = curl_exec ($ch);

    $curl_return=array();

    if (!is_string($result))
        {
        $curl_return['STATUS'] = FALSE;
        $curl_return['ERRMSG'] = curl_error($ch);
        }
    else
        {
        $curl_return['STATUS'] = TRUE;
        $curl_return['RESPONSE'] = $result;
        }
    curl_close($ch); 
    return $curl_return;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接