更新:请参阅消息末尾的新代码,这实际上用 cURL 很容易做到,但我第一次做错了。
我无法让 Twitter 流 API 使用 cURL 和 a 一起工作,CURLOPT_READFUNCTION
但使用fsockopen()和fread()
. 我不确定为什么 readfunction 没有像我之前成功使用它那样工作,但它一定与响应数据是“流式传输”并且不是使用 HTTP 分块编码发送的事实有关。本质上,我的读取函数从未被调用,因此我无法处理数据。
我使用的方法现在有效:
- 使用 fsockopen 连接到
ssl://stream.twitter.com
- 使用流数据发出基本 HTTP 请求
fputs
- 使用 HTTP 响应标头并确保没有错误
fread
使用无限循环读取数量数据
- 每次读取一大块数据时,我都会调用一个内部缓冲区函数
- 缓冲区函数将新数据附加到缓冲区
- 缓冲区函数然后尝试处理缓冲区中的所有消息(如果我们有 1 条或更多完整消息)
- 在处理每条消息时,缓冲区会减少,直到它为空,然后函数返回并再次读取数据
我已经让它运行了几个小时,并且没有断开连接,并且我已经处理了超过 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);