PythonとVKの友情の分析

最近、Wabrram Mathematicaを使用したVKontakteでの友情の実装に関する記事がHabréに掲載されました。 私はこのアイデアが気に入りました。もちろん、Pythonとd3を使用して同じグラフを作成したかったのです。 これがその結果です。



注意! 記事にはコードの一部があり、最も重要なアクションを説明していますが、プロジェクトのコードベースが複数変更されることに注意してください。 興味がある人はGitHubでソースを見つけることができます。



タスクを要素に分割します。



これに必要なもの:



アプリケーションの作成と承認



VKontakte APIにアクセスするには、 スタンドアロンアプリケーションを作成する必要があります 。その後、必要なAPIメソッドを使用できます。これについては後で説明します。 ここでアプリケーションが作成されます - スタンドアロンアプリケーションを選択します 。 モバイルに送信された確認コードを入力するよう求められます。その後、アプリケーション管理ページに移動します。 [設定 ]タブで、 access_tokenアプリケーションIDが役立ちます。

次に、アプリケーションを認証する必要があります。 このプロセスは3つのステージで構成されます。



VKでのユーザー認証


これを行うには、以下に示すようにURLを構成します。









https://oauth.vk.com/authorize?client_id=ID&scope=friends,offline&redirect_uri=https://oauth.vk.com/blank.html&display=page&v=5.21&response_type=token
      
      





vk.com/dev/auth_mobileを引用:

APP_ID-アプリケーションの識別子。

許可-要求されたアプリケーションの許可。

DISPLAY-サポートされている承認ウィンドウの外観:ページ、ポップアップ、モバイル。

REDIRECT_URI-access_tokenの送信先アドレス。

API_VERSIONは、使用しているAPIのバージョンです。


私たちの場合、PERMISSIONSは、サードパーティのサーバーからいつでも友人やAPIにアクセスできます(永久トークン)。 アドレスが正しく形成されている場合、ユーザー名とパスワードの入力を求められます。



データへのアクセス許可


次に、アプリケーションが必要な情報にアクセスできるようにします。







access_tokenの取得


アプリケーションの承認後、クライアントはREDIRECT_URIにリダイレクトされます。 必要な情報はリンクで囲まれます。



 https://oauth.vk.com/blank.html#access_token=ACCESS_TOKEN&expires_in=0&user_id=USER_ID
      
      





settings.pyファイルを編集し、受け取ったaccess_tokenuser_idをそこに挿入します 。 これで、VK APIにリクエストを送信できます。



データ検索



まず、この目的のために使用する方法を分析します。



グラフを作成するユーザーのIDに関する情報が少なくとも必要なので、 users.getは便利です。 これは、1つのIDと複数のフィールド、フィールドのリスト、必要な情報、および姓と名が傾く場合の両方を受け入れます。 base_info()メソッドはIDリストを取得し、写真を持つユーザーに関する情報を返します。



 def base_info(self, ids): """read https://vk.com/dev/users.get""" r = requests.get(self.request_url('users.get', 'user_ids=%s&fields=photo' % (','.join(map(str, ids))))).json() if 'error' in r.keys(): raise VkException('Error message: %s. Error code: %s' % (r['error']['error_msg'], r['error']['error_code'])) r = r['response'] # ,  id  settings.py   if 'deactivated' in r[0].keys(): raise VkException("User deactivated") return r
      
      





これはfriends.getMutualからidを送信したい人にとって重要であり、膨大な数のリクエストを発生させます。 それについては後で詳しく説明します。

ここで、ユーザーの友達に関する情報を取得する必要があります。これはfriends.getメソッドで役立ちます。 ドキュメントにリストされているすべてのパラメーターのうち、 setting.pyfieldsにあるuser_idを使用します 。 追加のフィールドは、友人のID、名前、姓、写真になります。 結局、ノードに写真のサムネイルを持たせたいのです。



 def friends(self, id): """ read https://vk.com/dev/friends.get    """ r = requests.get(self.request_url('friends.get', 'user_id=%s&fields=uid,first_name,last_name,photo' % id)).json()['response'] #self.count_friends = r['count'] return {item['id']: item for item in r['items']}
      
      





次に楽しい部分があります。

2人のユーザー間の共通の友人のIDリストはfriends.getMutualメソッドを返します。 friends.getのおかげで、idを取得するだけで、より高度な情報を既に取得しているため、これは良いことです。 しかし、 users.getを使用してさらに100から2つのリクエストを行うことを禁止する人はいません。 スキームは少し下にあります。

ここでfriends.getMutualの使用方法を決定しましょう。 ユーザーにN人の友人がいる場合は、N人のリクエストを作成して、友​​人ごとに共通の友人のリストを取得する必要があります。 さらに、1秒あたりの有効なリクエスト数を確保するために、遅延を作成する必要があります。

スキャンするIDに25人の友人がいるとします。





リクエストが多すぎるのは52件だけなので、 users.getはidリストを受け入れることができることに注意しください





25人の友人-28のリクエスト。ただし、上記のようにfriends.getのおかげですでに情報があります。







そして、ここでexecuteは便利であり、メソッドのシーケンスを実行できます。 単一のコードパラメーターがあり、APIメソッドへの最大25の呼び出しを含めることができます。

つまり、最終的に、 VKScriptのコードは次のようになります。



 return { “id": API.friends.getMutual({"source_uid":source, "target_uid":target}), // * 25 ... };
      
      





API.friends.getMutualを常に使用せずにこのコードを短縮する方法を書く人がいます。

ここで、それぞれ25の友人IDのバッチで送信する必要があります。 この例では、回路は次のようになります。







しかし、forを使用して各友人をfriends.getMutualに送信し、users.getを介してより詳細な情報を見つけることができます。

次に、人間が読み取れる構造を作成します。ここでは、友人のIDと共通の友人のIDリストの代わりにfriends.getからの情報があります。 その結果、次のような結果が得られます。



 [({ }, [{ }, {   }]),({ }, None)]
      
      





辞書には、id、名、姓、写真がリストにあります-共通の友人の辞書、共通の友人がいない場合はなし。 タプルはすべて分割されています。



 def common_friends(self): """ read https://vk.com/dev/friends.getMutual and read https://vk.com/dev/execute               """ def parts(lst, n=25): """     -  25   """ return [lst[i:i + n] for i in iter(range(0, len(lst), n))] result = [] for i in parts(list(self.all_friends.keys())): #  code ( execute) code = 'return {' for id in i: code = '%s%s' % (code, '"%s": API.friends.getMutual({"source_uid":%s, "target_uid":%s}),' % (id, self.my_id, id)) code = '%s%s' % (code, '};') for key, val in requests.get(self.request_url('execute', 'code=%s' % code)).json()['response'].items(): if int(key) in list(self.all_friends.keys()): #       result.append((self.all_friends[int(key)], [self.all_friends[int(i)] for i in val] if val else None)) return result
      
      





そのため、友達のリストとその友達との共通の友達を表示するには、次を実行します。



 python main.py
      
      





グラフの視覚化



選択肢はd3 、つまりCurved Linksにありました 。 これを行うには、次のようなjsonを生成します。



 { "nodes": [ {"name":"Myriel","group":1, "photo": "path"}, {"name":"Napoleon","group":1, "photo": "path"}, {"name":"Mlle.Baptistine","group":1, "photo": "path"} ], "links":[ {"source":1,"target":0,"value":1}, {"source":2,"target":0,"value":8} ] }
      
      





index.htmlを少し変更すると 、友人の写真がノードになります。



すぐにグラフを視覚化する場合:



 python 2d3.py
      
      





miserables.jsonファイルがWebフォルダーに表示されます。 Mozilla FireFoxでindex.htmlを開くか、 python -m http.server 8000を使用してChromeで開くことを忘れないでください。



多数の友人がいると視覚化が遅くなるため、将来的にはWebGLの使用を検討しています。



これは私の友人の一人の友情グラフがどのように見えるかです。 コミュニケーションがすべてです。







もちろん、私は誰がより速く働くのだろうと思っていました。



私にインスピレーションを与えた記事はこう言います

私の333人の友人では、119秒かかりました。






この記事の執筆時点で、HimuraにはVKontakteに321人の友人がいました。 9秒かかりました( friends.getMutualだけでなく、プログラム全体)。



結論として



使用されるメソッドに関するすべての必要な情報は、VKontakteの寛大に書かれたドキュメントで見つけることができますが、いくつかのエラーが見つかりました:エラーコード15が記述されていません( 「error_msg」:「Access denied:user deactivated」、「error_code」:15 )、推測できます、その意味、およびfriends.getメソッドのドキュメントのuser_idではなくuid 。 2日後:









冒頭で述べたように、プロジェクトはGitHubで見つけることができます。他の誰かがそれを気に入ってくれてうれしいです。そして、たくさんのおいしいプルリクエストを受け取ります...



UPD(2014年5月27日):

WTFRU7 私を 促し ので、ストアドプロシージャを使用する機能を追加しました。 これを行うには、 リンクをたどってください

getMutualストアドプロシージャを作成します。 execute_getMutual.jsの内容をフォームにコピーして保存します。 新しいバージョンをダウンロードすることを忘れないでください。 スキームの最終形式は次のとおりです。







UPD(2014年6月16日):

無制限のトークンを取得します。

UPD(2014年7月11日):

説明スキームが追加されました。

UPD(2014年11月14日):

継続



All Articles