我正在制作一个应用程序,该应用程序使用Twitter API接收用户的推文,其中一个组件是从推文文本中提取情感。为了进行开发,我使用了examplep,当然也使用ApacheHTMLServer作为我的工作区。我使用Eclipse for PHP作为IDE。
对于情感提取,我使用uClassify情感分类器。分类器使用API来接收大量请求,并随每个请求发送回XML数据,从中可以解析情感值。
现在,应用程序可以同时处理大量的推文(允许的最大值为3200)。例如,如果有3200条推文,那么系统将同时向该分类器发送3200个API调用。不幸的是,对于这个数字,系统不能很好地扩展,事实上,xampp在使用这些调用运行系统很短一段时间后就会崩溃。然而,对于少量的tweet(例如500条tweet),系统运行良好,所以我假设这可能是由于大量的API调用。值得注意的是,uClassify每天允许的API调用的最大数量是5000,但由于最大数量是3200,我很确定它不会超过这个数字。
这几乎是我第一次从事这种网络开发,所以我不确定我在这里是否犯了一个新手错误。我不知道自己做错了什么,也不知道从哪里开始寻找。任何建议/见解都会有很大帮助!
EDIT:添加了有问题的源代码
更新索引方法
function updateIndex($timeline, $connection, $user_handle, $json_index, $most_recent) {
// URL arrays for uClassify API calls
$urls = [ ];
$urls_id = [ ];
// halt if no more new tweets are found
$halt = false;
// set to 1 to skip first tweet after 1st batch
$j = 0;
// count number of new tweets indexed
$count = 0;
while ( (count ( $timeline ) != 1 || $j == 0) && $halt == false ) {
$no_of_tweets_in_batch = 0;
$n = $j;
while ( ($n < count ( $timeline )) && $halt == false ) {
$tweet_id = $timeline [$n]->id_str;
if ($tweet_id > $most_recent) {
$text = $timeline [$n]->text;
$tokens = parseTweet ( $text );
$coord = extractLocation ( $timeline, $n );
addSentimentURL ( $text, $tweet_id, $urls, $urls_id );
$keywords = makeEntry ( $tokens, $tweet_id, $coord, $text );
foreach ( $keywords as $type ) {
$json_index [] = $type;
}
$n ++;
$no_of_tweets_in_batch ++;
} else {
$halt = true;
}
}
if ($halt == false) {
$tweet_id = $timeline [$n - 1]->id_str;
$timeline = $connection->get ( 'statuses/user_timeline', array (
'screen_name' => $user_handle,
'count' => 200,
'max_id' => $tweet_id
) );
// skip 1st tweet after 1st batch
$j = 1;
}
$count += $no_of_tweets_in_batch;
}
$json_index = extractSentiments ( $urls, $urls_id, $json_index );
echo 'Number of tweets indexed: ' . ($count);
return $json_index;
}
提取情感方法
function extractSentiments($urls, $urls_id, &$json_index) {
$responses = multiHandle ( $urls );
// add sentiments to all index entries
foreach ( $json_index as $i => $term ) {
$tweet_id = $term ['tweet_id'];
foreach ( $urls_id as $j => $id ) {
if ($tweet_id == $id) {
$sentiment = parseSentiment ( $responses [$j] );
$json_index [$i] ['sentiment'] = $sentiment;
}
}
}
return $json_index;
}
处理多个API调用的方法
这是同时处理uClassify API调用的地方:
function multiHandle($urls) {
// curl handles
$curls = array ();
// results returned in xml
$xml = array ();
// init multi handle
$mh = curl_multi_init ();
foreach ( $urls as $i => $d ) {
// init curl handle
$curls [$i] = curl_init ();
$url = (is_array ( $d ) && ! empty ( $d ['url'] )) ? $d ['url'] : $d;
// set url to curl handle
curl_setopt ( $curls [$i], CURLOPT_URL, $url );
// on success, return actual result rather than true
curl_setopt ( $curls [$i], CURLOPT_RETURNTRANSFER, 1 );
// add curl handle to multi handle
curl_multi_add_handle ( $mh, $curls [$i] );
}
// execute the handles
$active = null;
do {
curl_multi_exec ( $mh, $active );
} while ( $active > 0 );
// get xml and flush handles
foreach ( $curls as $i => $ch ) {
$xml [$i] = curl_multi_getcontent ( $ch );
curl_multi_remove_handle ( $mh, $ch );
}
// close multi handle
curl_multi_close ( $mh );
return $xml;
}
问题是一次给curl提供了太多的URL。我很惊讶你能同时管理500个,因为我看到人们甚至抱怨200个有问题。这家伙有一些聪明的代码,每次只写100个,但每次完成后都会添加下一个,但我注意到他把它编辑成每次只写5个。
我刚刚注意到该代码的作者围绕这个想法发布了一个开源库,所以我认为这就是适合你的解决方案:https://github.com/joshfraser/rolling-curl
关于为什么会崩溃,关于这个问题的评论表明,原因可能是达到了操作系统文件句柄的最大数量:cURL连接的最大数量是多少?而其他建议只是简单地使用大量的带宽、CPU和内存。(如果您在windows上,打开任务管理器应该可以查看情况是否如此;在linux上使用top
)