Я делаю приложение, которое принимает твиты пользователя с помощью API Twitter, и одним из его компонентов является извлечение настроений из текстов твитов. Для разработки я использую xampp, конечно, используя Apache HTML Server в качестве рабочей области. Я использую Eclipse для PHP в качестве IDE.
Для извлечения настроения я использую u Классифицировать классификатор настроений. Классификатор использует API для получения ряда запросов и при каждом запросе отправляет обратно данные XML, из которых можно анализировать значения настроений.
Теперь приложение может обрабатывать большое количество твитов (максимально допустимое значение — 3200) одновременно. Например, если есть 3200 твитов, то система отправит 3200 вызовов API одновременно этому классификатору. К сожалению, для этого номера система плохо масштабируется, и на самом деле xampp аварийно завершает работу через некоторое время после запуска системы с этими вызовами. Однако при небольшом количестве твитов (например, 500 твитов) система работает нормально, поэтому я предполагаю, что это может быть связано с большим количеством вызовов API. Это может помочь заметить, что максимальное количество вызовов API, разрешенных uClassify в день, составляет 5000, но, поскольку максимальное значение составляет 3200, я почти уверен, что оно не превышает это число.
Я впервые работаю над этим видом веб-разработки, поэтому я не уверен, что здесь я делаю ошибку новичка. Я не уверен, что могу делать не так, и не знаю, с чего начать. Любой совет / понимание поможет очень!
РЕДАКТИРОВАТЬ: добавлен исходный код в вопросе
Обновить метод индекса
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
Это где вызовы API uClassify обрабатываются сразу:
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;
}
Проблема заключается в том, чтобы дать слишком много URL за один раз. Я удивлен, что вы можете управлять 500 параллельно, поскольку я видел, как люди жалуются на проблемы даже с 200. У этого парня есть какой-то умный код до 100 за раз, но затем добавляйте следующий каждый раз, когда каждый заканчивает, но я замечаю, что он отредактировал его, чтобы просто сделать 5 за раз.
Я только что заметил, что автор этого кода выпустил библиотеку с открытым исходным кодом вокруг этой идеи, поэтому я думаю, что это решение для вас: https://github.com/joshfraser/rolling-curl
Относительно того, почему вы получаете сбой, комментарий на этот вопрос предполагает, что причина может достигать максимального числа дескрипторов файла ОС: Какое максимальное количество соединений cURL установлено? и другие предложения просто используют много пропускной способности, процессора и памяти. (Если вы находитесь в Windows, открытие диспетчера задач должно позволить вам увидеть, так ли это; при использовании Linux top
)
Других решений пока нет …