Pythonを使用してすべてのVKユーザーとチャット履歴をダウンロードする

言語研究のために、私は一人の人間によって生成された直接的な音声の本体が必要でした。 まず最初に、VKで自分の通信を使用するのが最も便利であると判断しました。 この記事では、PythonプログラムとVKontakte APIを使用して友人に送信したすべてのメッセージをダウンロードする方法について説明します。 APIを使用するには、 vkライブラリを使用します。



サイトを操作するには、アプリケーションを作成し、トークンを使用してログインする必要があります。 このプロセスは複雑なものではなく、 ここここで説明さています



そのため、トークンが受信されます。 必要なライブラリーをインポートし(時間をかけて後で再作成します)、アプリケーションに接続して作業を開始します。



import vk import time import re session = vk.Session(access_token='your_token') vkapi = vk.API(session)
      
      





すべての友人と連絡を取りたいので、友人のリストを取得することから始めましょう。 友人の完全なリストのさらなる処理は非常に長くなる可能性があるため、テストのために、複数の友人のIDを手動で書き込むことができます。



 friends = vkapi('friends.get') #       # friends = [1111111, 2222222, 33333333] #   
      
      





友達のリストがあれば、すぐにそれらとのダイアログのダウンロードを開始できますが、200人以上のメッセージを含むダイアログのみを処理します。馴染みのない人との短い会話はあまり興味がありません。 したがって、ダイアログの「キャップ」を返す関数を作成します。



 def get_dialogs(user_id): dialogs = vkapi('messages.getDialogs', user_id=user_id) return dialogs
      
      





このような関数は、指定されたuser_idと等しいidを持つユーザーとのダイアログの「ヘッダー」を返します。 彼女の仕事の結果は次のようになります。



[96, {'title': ' ... ', 'body': '', 'mid': 333333, 'read_state': 1, 'uid': 111111, 'date': 1490182267, 'fwd_messages': [{'date': 1490173134, 'body': ', , .', 'uid': 222222}], 'out': 0}]







リストには、メッセージの数(96)とダイアログの最後のメッセージのデータが含まれます。 これで、必要なダイアログをダウンロードするために必要なものがすべて揃いました。



主な欠点は、VKontakteが1秒間に最大約3件のリクエストを作成できるため、各リクエストの後にしばらく待つ必要があることです。 このためには、タイムライブラリが必要です。 いくつかの操作の後に拒否されないように設定した最小の待機時間は0.3秒です。



もう1つの問題は、リクエストごとに最大200のメッセージをダウンロードできることです。 これも戦わなければなりません。 関数を書きましょう。



 def get_history(friends, sleep_time=0.3): all_history = [] i = 0 for friend in friends: friend_dialog = get_dialogs(friend) time.sleep(sleep_time) dialog_len = friend_dialog[0] friend_history = [] if dialog_len > 200: resid = dialog_len offset = 0 while resid > 0: friend_history += vkapi('messages.getHistory', user_id=friend, count=200, offset=offset) time.sleep(sleep_time) resid -= 200 offset += 200 if resid > 0: print('--processing', friend, ':', resid, 'of', dialog_len, 'messages left') all_history += friend_history i +=1 print('processed', i, 'friends of', len(friends)) return all_history
      
      





ここで何が起こるか見てみましょう。



友人のリストを調べて、それぞれの友人と対話します。 対話の長さを考慮します。 ダイアログが200メッセージより短い場合は、次の友人に移動し、それより長い場合は、最初の200メッセージ(引数カウント)をダウンロードし、この友人のメッセージ履歴に追加して、ダウンロードする残りのメッセージ(残余)を計算します。 剰余が0より大きい限り、各反復でオフセット引数を増やします。これにより、ダイアログの最後から200のメッセージ数をインデントできます。



各リクエストの後に待機する必要があるため、プログラムはかなり長い時間実行されるため、現在のステップに関する小さなレポートの出力を追加して、処理されているものと残っている量を把握しました。



注意:messages.getメソッドにはout引数があり、これを使用して、送信メッセージのみを送信するようサーバーに要求できます。 次の理由により、使用しないでダウンロード後に必要なメッセージを選択することにしました。a)ファイルを引き続きクリーンアップする必要があります。 サーバーは多くの技術情報を含む辞書の形式で各メッセージを提供します。b)対話者のメッセージも私の研究に興味があるかもしれません。



ダウンロードされた各メッセージは辞書であり、次のようになります。

{'read_state': 1, 'date': 1354794668, 'body': ' !<br> .', 'uid': 111111, 'mid': 222222, 'from_id': 111111, 'out': 1}







残るのは、結果を消去してファイルに保存することだけです。 作業のこの部分は、VK APIとの相互作用とは関係ないため、詳細については説明しません。 はい、私に言えること-ユーザーに必要な要素(本体)を選択し、reを使用して<br>



タグ付けされた改行を削除します。 すべてをファイルに保存します。



完全なプログラムコードは次のようになります。



 import vk import time import re session = vk.Session(access_token='your_token') vkapi = vk.API(session) SELF_ID = 111111 SLEEP_TIME = 0.3 friends = vkapi('friends.get') #        def get_dialogs(user_id): dialogs = vkapi('messages.getDialogs', user_id=user_id) return dialogs def get_history(friends, sleep_time=0.3): all_history = [] i = 0 for friend in friends: friend_dialog = get_dialogs(friend) time.sleep(sleep_time) dialog_len = friend_dialog[0] friend_history = [] if dialog_len > 200: resid = dialog_len offset = 0 while resid > 0: friend_history += vkapi('messages.getHistory', user_id=friend, count=200, offset=offset) time.sleep(sleep_time) resid -= 200 offset += 200 if resid > 0: print('--processing', friend, ':', resid, 'of', dialog_len, 'messages left') all_history += friend_history i +=1 print('processed', i, 'friends of', len(friends)) return all_history def get_messages_for_user(data, user_id): self_messages = [] for dialog in data: if type(dialog) == dict: if dialog['uid'] == user_id and dialog['from_id'] == user_id: m_text = re.sub("<br>", " ", dialog['body']) self_messages.append(m_text) print('Extracted', len(self_messages), 'messages in total') return self_messages def save_to_file(data, file_name='output.txt'): with open(file_name, 'w', encoding='utf-8') as f: print(data, file=f) if __name__ == '__main__': all_history = get_history(friends, SLEEP_TIME) save_to_file(all_history, 'raw.txt') self_messages = get_messages_for_user(all_history, SELF_ID) save_to_file(self_messages, 'sm_corpus.txt')
      
      





プログラムの開始時には、VKに879人の友人がいました。 それらの処理には約25分かかりました。 生の結果ファイルのサイズは74MBでした。 私の投稿のみのテキストを強調表示した後-15MB。 受信したコーパス内のメッセージの合計数は約150,000であり、テキストは3,707ページ(Word文書内)になります。



私の記事が誰かに役立つことを願っています。 VK APIにアクセスするために使用できるすべてのメソッドは VKontakte 開発者向けセクションで詳細に説明されています。



All Articles