VKグループのアクティビティを監視します。 VKScriptでデータを処理します

よく知られているソーシャルネットワークによってユーザーのアクティビティを監視するタスクに直面しました。 私の仕事は、特定のグループまたはコミュニティでオンラインになっているユーザーの数に関するデータを収集することでした。



ツール


私自身はWeb開発に携わっているため、使用したツールは



私の選択-Vk API-を説明します。事実、APIなしで、ユーザー検索ページをコミュニティフィルターとオンラインタグでコード化することで、ユーザー数をオンラインで取得できます。



建築


実装は条件付きで2つの部分に分割できます。 1つ目は、グループIDでオンラインのユーザー数を検出し、データベースに書き込むスクリプトです。 2つ目は管理パネルです。このパネルでは、監視用の新しいグループを追加し、既に追加されているグループの統計を表示できます。

統計が関連するためには、可能な限り頻繁に現在の時間にグループのステータスを監視する必要があります。 スクリプトはCronにぶら下がる価値があります。5分ごとに呼び出されます。



Vk APIの概要


管理パネルですべてが多かれ少なかれ明確な場合、統計を収集するスクリプトでは完全に明確ではありません。 APIが提供するメソッドに慣れてきたので、最初の解決策を見つけました。



最初の解決策(間違った)


groups.getMembersusers.getメソッドを使用して、グループメンバーとそのステータス(オンラインまたはオフライン)のリスト取得します。 次に、オンラインのユーザー数をカウントします。 すべてがシンプルです。 ただし、明らかな単純さは多くの問題をもたらします。

小グループ(1000人まで)があれば、すべてがうまくいくでしょう。 そうしないと、APIの制限に直面します-一度に1000人のユーザーに関する情報しか取得できません。 この制限は何ですか?メソッドをループで呼び出すことができますが、できません。 API呼び出しを行うことは、1秒あたり3リクエストまで許可されます。

必要なクエリのおおよその数を計算します。 habrahabrコミュニティVkを利用してください。 40,000人を超えるユーザーがいるため、コミュニティメンバーを取得するには40件のリクエストが必要であり、ステータスは40件です。

新しいソリューションを探し始めました。



2番目の解決策(正しい)


ドキュメントでexecuteメソッドを見つけます

他のメソッドのシーケンスを実行し、中間結果を保存およびフィルタリングできる汎用メソッド。


いわゆるVKScript(javascriptに類似)で記述されたコードを含む入力行が必要です。 唯一の問題は、このメソッドと言語自体に関する正しいドキュメントがないことです。 おそらく解決策が見つかったので、特にVk APIとVKScriptの研究をさらに深くすることができます。



APIを使用する


開発者が提供するAPIクラスをダウンロードします。 Zend Frameworkで使用されているコーディングスタイルに適合するように、私はそれをより受け入れやすい形式にしました。

クラスAPI
<?php class Vkapi_Model_Api { private $_accessToken = null; private $_apiUrl = 'https://api.vk.com/method/'; public function __construct($accessToken) { $this->_accessToken = $accessToken; } public function api($method, $params = array()) { $params['access_token'] = $this->_accessToken; $query = $this->_apiUrl. $method . '?' . $this->_params($params); $responseStr = file_get_contents($query); if(!is_string($responseStr)){ return null; } $responseObj = json_decode($responseStr); return $responseObj; } private function _params($params) { $pice = array(); foreach($params as $k=>$v) { $pice[] = $k.'='.urlencode($v); } return implode('&',$pice); } }
      
      





認証と承認は、OAuth、インターネット、およびVk APIページの多くの情報を通じて実行されるため、説明しません。



APIをテストコールしてみましょう-habrahabrグループの最初の20の投稿を取得します

  public function wallsAction() { //....... $api = new Vkapi_Model_Api($accessToken); $response = $api->api('wall.get',array('owner_id' => '-20629724')); $this->view->walls = $response->response; }
      
      





画像



次に、 executeメソッドを介してのみ同じことを行います。



  public function wallsAction() { //....... $api = new Vkapi_Model_Api($accessToken); $code = " var walls = API.wall.get({ owner_id : -20629724 }); return walls; "; $response = $api->api('execute',array('code' => $code )); $this->view->walls = $response->response; }
      
      





その結果、同じ結果が得られます。

悪い点の1つは、VKScriptとPHPコードを混合したことです。 とても悪いようです。 リファクタリングをしましょう。

各スクリプトが個別のファイルに保存されていて、1つの関数で呼び出すことができれば便利です。 また、後でこのスクリプトにデータを転送する必要があることを提供する必要もあります(たとえば、 owner_idはコードにハードコードされています)。



VKScriptを個別のファイルで取り出します


モジュールのルートに「vkscripts」というフォルダーを作成し、スクリプトを追加します(たとえば、getWalls.vks)。 application.ini構成ファイルにスクリプトへのパスを書き込みます

 vkapi.scripts.path = APPLICATION_PATH "/modules/vkapi/vkscripts"
      
      





このディレクトリにあるスクリプトを呼び出すのに便利なクラスが必要です。 PHP5の機能、つまり魔法の__callメソッドを使用します。 呼び出されたメソッドの名前で、その名前のスクリプトを探します。

クラスソース
 <?php class Vkapi_Model_Executor { private $_api; public function __construct($api) { $this->_api = $api; } public function __call( $methodName, $arguments ) { $script = $this->_getScript($methodName); if(count($arguments)){ $script = $this->_prepareParams($script, $arguments[0]); } $response = $this->_api->api('execute', array('code' => $script)); if( $error = $this->_getError($response) ){ throw new Exception($error->error_msg, $error->error_code); } return $response->response; } private function _getError($response) { if( isset($response->error) ){ $error = $response->error; return $error; } return null; } private function _getScript( $name ) { $scriptsPath = Zend_Registry::get('vkapi_config')->scripts->path; $filePath = $scriptsPath . '/' . $name . '.vks'; if(is_file($filePath)){ $script = file_get_contents($filePath); return $script; } return null; } }
      
      





それでは、このクラスで何かをしましょう。

vkscriptsフォルダーに、そのようなコンテンツを含むgetWalls.vksファイルを配置します

 var walls = API.wall.get({ owner_id : -20629724 }); return walls;
      
      





コントローラー内:

  public function wallsAction() { //....... $api = new Vkapi_Model_Api($accessToken); $executor = new Vkapi_Model_Executor($api); $response = $executor->getWalls(); $this->view->walls = $response->response; }
      
      





同じ結果が得られましたが、大きな利点があります。コードを個別のファイルに分割し、読みやすくし、実行の呼び出しを単純化しました。

次のステップは、スクリプトにパラメーターを渡す機能を追加することです。 これには特定の表現を使用します。 VKScriptコードでは、必要に応じて、最初に次のように入力に何かを記述します。

 var groupId = %GROUP_ID%; var offset = %OFFSET%; // ....    
      
      





そしてこのクラスでは、このコードでAPIを呼び出す前に、%VAR_NAME%を変数の値に置き換えます。

クラスエグゼキューターを次のように追加しましょう

変更されたクラスソース
 <source lang="php"> <?php class Vkapi_Model_Executor { // ...... public function __call( $methodName, $arguments ) { $script = $this->_getScript($methodName); if(count($arguments)){ $script = $this->_prepareParams($script, $arguments[0]); } $response = $this->_api->api('execute', array('code' => $script)); if( $error = $this->_getError($response) ){ throw new Exception($error->error_msg, $error->error_code); } return $response->response; } // ...... private function _prepareParams($script, $params) { foreach ($params as $key => $value){ $script = str_replace('%' . strtoupper($key) . '%', $value, $script); } return $script; } }
      
      





コントローラーでは、パラメーターを転送する必要がある場合、次のように記述します。

  public function wallsAction() { //....... $api = new Vkapi_Model_Api($accessToken); $executor = new Vkapi_Model_Executor($api); $response = $executor->getWalls(array( 'group_id' => -20629724, 'offset' => 0 )); $this->view->walls = $response->response; }
      
      





これにより、渡された値がスクリプトの%GROUP_ID%および%OFFSET%に置き換えられます。

これはモジュール構造のようです

画像

オンラインでユーザー数を取得する


executeで APIメソッドを呼び出すには制限があります。 22コールを制限します(ほぼ見つかりました)。 また、Web上では、他の演算子に制限(たとえば、加算、減算)があるという情報は見つかりませんでしたが、いくつかあります。 ユーザーの配列を実行し、オンラインで数を数えた場合、超過した操作数に関するエラーを受け取ったため、実行からユーザーの完全なリストを返すことにしました。その後、ユーザー数を数えるためにサーバー側に既にありました。

executeメソッドのAPIリクエストの数が限られているため 、1,000を処理するには2つのリクエストが必要なため、グループのメンバー10,000人に対して少なくとも1つのリクエストを実行する必要があります。

これが判明したスクリプトです

 var groupId = %GROUP_ID%; var offset = %OFFSET%; // API call limit var _acl = 22; var members = API.groups.getMembers({ gid : groupId }); _acl = _acl - 1; var count = members.count; var users = []; while( _acl > 1 && offset < count){ var _members = API.groups.getMembers({ gid : groupId, offset : offset }); _acl = _acl - 1; users = users + API.users.get({ uids : members.users, fields : "online" }); _acl = _acl - 1; offset = offset + 1000; } var result = { count : count, offset : offset, users : users@.online }; return result;
      
      





コードについて少しコメントします。 _Aclカウンター-APIの操作の制限を超えたことによるエラーを防止します。 users @ .online-値のリスト[0,1,1,0,0,0,1,0,1]のみをオンラインおよびオフラインで返します。

コントローラーでは、グループのすべてのメンバーを調べるまで、このスクリプトを呼び出し、オフセットを順番に増やします。

  $count = 1; $offset = 0; $nowOnline = 0; while($count > $offset){ $users = $executor->getOnline(array( 'group_id' => $groupId, 'offset' => $offset )); $count = $users->count; $offset = $users->offset; foreach ( $users->users as $online){ if($online){ $nowOnline++; } } }
      
      







したがって、抗議し、確認します-APIを介して受信したデータはvk.comからのデータとほぼ一致します。おそらくこの不正確さはキャッシュによるか、または別の理由で外部から見えません。

備考


VKScriptは、関数、増分、減分演算子をサポートしていません。



まとめ


executeメソッドを介してvk.com APIを操作するためのツールを開発しました。 これを使用して、統計収集アプリケーションなどを開発できます。 とても素敵に見えます。 これらすべてにインターフェースをねじ込むのは、すでに簡単な作業です。 最後に、別のソーシャルネットワークFacebookは、FQL(Facebookクエリ言語、SQLに類似)と呼ばれる言語で記述されたコードの実行へのアクセスを提供します。



参照資料


VK API

executeメソッド、VKScriptの簡単な説明と例

Facebookクエリ言語



All Articles