特定の性別と年齢のVKontakteコミュニティメンバーのリストを取得します

出版物「Getting vk.com Community Members in Seconds」により、この記事を作成することに触発されました。 私の記事は初心者によって書かれており、1つの問題を解決した経験を反映しています。 私のためにこの記事を書く主な目的は、経験豊富な同僚から意見、フィードバック、および適用されたアプローチに対する批判を集めることです。 さらに、ここで提供される情報が誰かに役立つことを願っています。



少し前のことですが、ジュニアphpプログラマーの欠員に関するテストタスクの1つで、単純だが興味深いタスクに出会いました。



「VKontakteのユーザーIDのリストを返すphpスクリプトを作成します。このスクリプトは、25歳以上の男性で、 vk.com / habrグループに属する改行文字で区切られています。」



VKontakteデータベースからの情報へのアクセスは、VK APIを使用して実行されます。 VK APIの使用を開始するには、 公式のドキュメントを使用する方が適切です。 VK API APIメソッドを呼び出すには、HTTPSを介して次の形式のURLにPOSTまたはGETリクエストを行う必要があります。



api.vk.com/method/METHOD_NAME?PARAMETERS&access_token=ACCESS_TOKEN。METHOD_NAMEはAPIメソッドのリストにあるメソッドの名前、PARAMETERSは対応するメソッドのパラメーター、ACCESS_TOKENはアクセスキーです。



このタスクでは、コミュニティメンバーのリストを返すgroups.getMembersメソッドを使用します。 すべてのメソッドパラメータはドキュメントに記載されています。 このメソッドはアクセスキーを必要としません。 標準形式では、応答はJSONファイルの形式で提供されます。 1つのリクエストで、最大1000ユーザーのデータを取得できます。 メソッドの出力をライブで表示するには、ブラウザのアドレスバーに最も単純なリクエストapi.vk.com/method/groups.getMembers?group_id=habrを入力するだけです



コミュニティメンバーvk.com/habrの総数とデフォルトリストの最初の1000のIDが昇順にソートされ JSON構造を取得します。



タスクの条件により、特定の性別と年齢のユーザーのIDを表示する必要があります。 明白な方法は、性別と年齢のデータとともにVK APIリクエストでグループユーザーを選択し、PHPコードでそれらを分析し、必要なもののみを表示することです。 別の可能なメソッド-executeメソッド-サーバー上のデータを操作するための特別な言語VKScriptで特別なリクエストでスクリプトを転送し、処理済みのデータを返すことができます。 executeメソッドを使用して問題を解決できなかったことをすぐに言わなければなりません。 たぶん、コメントで誰かがそのような決定を示すでしょう。



最初の道に行きましょう。 groups.getMembersメソッドは、fieldsパラメーターの性別の値を使用して、ユーザーの性別を返すことができますが、年齢は示しません。 代わりに、fieldsパラメーターにはbdateフィールド(生年月日)があります。 さらに、クエリでは、1000人のユーザーを選択します。つまり、次のリクエストごとに次の1000人が発行されます。 これを行うために、サンプリングを開始する位置を示すオフセットパラメーターがあります。 また、リクエストでAPIのバージョンを示します。



その結果、リクエストは次のようになります。https : //api.vk.com/method/groups.getMembers?group_id=habr&offset=0&fields=sex,bdate&version=5.27



参照によりファイルを取得するために、PHPにはfile_get_contents()関数があります。 彼女は参照によってコンテンツを受け取り、それを文字列として返します。 file_get_contents()がHTTPSプロトコルを理解するには、Webサーバーでopensslサポートが必要であることに注意してください。



次に、 json_decode()関数を使用して、結果のJSONコンテンツを配列に変換できます。 配列にはidと性別の両方が含まれます。 生年月日はまったく表示されない場合があります。

生年月日がまだ示されている場合、生年月日から年齢を取得するために残ります。



bdateの生年月日は、生年が指定されている場合はDD.MM.YYYY形式の行に、生年が指定されていない場合はDD.MMの行に格納されます。 文字列が実際にどの形式であるかを調べるために、最初に思いついたものを使用しました:count(explode( "。"、$ User_array ['bdate']))は2または3です。この方法は機能し、最も狭いとは思いませんスクリプトの場所。



生年月日で年齢を計算するために、彼は式hashcode.ru/questions/137939#137940を見つけました。 strtotime()関数は、bdateフィールドの形式を理解します。



性別と年齢を確認します。 条件を満たす場合は、idを出力します。

すべてのPHPコード
//    $packet = 0; //    $limit = 1000; do { //    ,     . $offset = $ packet * $limit; //  . //  - JSON-      . //  file_get_contents()   https  - apache //     openssl. $contents = file_get_contents("https://api.vk.com/method/groups.getMembers?group_id=habr&offset=$offset&fields=sex,bdate&version=5.27") //  JSON   $members = json_decode($contents, true); //      users. //   users -    . foreach ($members['response']['users'] as $user_array) { //        - ... if ((isset($user_array['bdate'])) && ($user_array['sex'] == 2)) { // ...        (..)... if (count(explode(".", $user_array['bdate'])) == 3) { //    (   ) $age = floor((time()-strtotime($user_array['bdate']))/(60*60*24*365.25)); //    ,  id     if ($age > 25) { echo $user_array['uid'] . "<br/>"; } } } } //    . $packet++; } while ($members['response']['count'] > $offset + $limit);
      
      







このオプションは、比較的小さなグループではうまく機能しますが、10万人を超えるサブスクライバーのグループでは、スクリプトは最後まで機能しません-ある時点でエラー「file_get_contents(...):ストリームを開くことができません:接続がタイムアウトしました...ライン上... "。 スクリプトの実行時間とWebサーバーのタイムアウトを増加させようとしました-助けにはなりませんでした。 パターンが見つかりませんでした。



その後、別のオプションが見つかりました-cURLを使用して要求応答をロードします。 この方法を使用するには、OS、たとえばUbuntuにlibcurlライブラリをインストールする必要があります-
 sudo apt-get install libcurl3
      
      



UbuntuなどのPHPでcURLサポートを有効にします-
 sudo apt-get install php5-curl
      
      



これで、PHPスクリプトでcurl_init()関数を使用してcurlセッションを開き、 curl_setopt()関数を使用して接続パラメーター(URLを含む)を設定し、 curl_exec()関数を使用してJSONファイルの内容を文字列にダウンロードできます。 次に、セッションcurl_close()を閉じる必要があります。 残りのコードは変更されません。

PHPのすべてのcURLコード
 //    $packet = 0; //    $limit = 1000; //  cURL. //    cURL     libcurl //    cURL  PHP. $ch = curl_init(); do { //    ,     . $offset = $ packet * $limit; //   curl_setopt($ch, CURLOPT_URL, "https://api.vk.com/method/groups.getMembers?group_id=habr&offset=$offset&fields=sex,bdate&version=5.27"); curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); //  . //  - JSON-      . $content = curl_exec ($ch); $members = json_decode($contents, true); //      users. //   users -    . foreach ($members['response']['users'] as $user_array) { //        - ... if ((isset($user_array['bdate'])) && ($user_array['sex'] == 2)) { // ...        (..)... if (count(explode(".", $user_array['bdate'])) == 3) { //    (   ) $age = floor((time()-strtotime($user_array['bdate']))/(60*60*24*365.25)); //    ,  id     if ($age > 25) { echo $user_array['uid'] . "<br/>"; } } } } //    . $packet++; } while ($members['response']['count'] > $offset + $limit); //  cURL curl_close ($ch);
      
      







先ほど言ったように、executeメソッドを使用したアプローチは可能だと思いますが、これまでのところ、この方向で満足のいく結果を得ることができませんでした。



PS Habrの聴衆からテストタスクの解決策を得たいと思わないようにお願いします。 かなり前に上記のオプションを送信し、応答を受け取りました。 私はこのタスクに多くの時間を費やしましたが、正しい方向に進んでいるかどうか、他にどのようなアプローチを使用できるかを知りたいと思います。



All Articles