Advertisement
Dzham

Untitled

May 21st, 2021
339
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.37 KB | None | 0 0
  1. import sys
  2. import time
  3. import requests
  4. import pickle
  5. from concurrent.futures import ThreadPoolExecutor
  6. from settings import token, my_id, api_v, max_workers, delay, deep
  7.  
  8. def force(f, delay=delay):
  9. """При неудачном запросе сделать паузу и попробовать снова"""
  10. def tmp(*args, **kwargs):
  11. while True:
  12. try:
  13. res = f(*args, **kwargs)
  14. break
  15. except KeyError:
  16. time.sleep(delay)
  17. return res
  18. return tmp
  19.  
  20. class VkException(Exception):
  21. def __init__(self, message):
  22. self.message = message
  23.  
  24. def __str__(self):
  25. return self.message
  26.  
  27.  
  28. class VkFriends():
  29. """
  30. Находит друзей, находит общих друзей
  31. """
  32. parts = lambda lst, n=25: (lst[i:i + n] for i in iter(range(0, len(lst), n)))
  33. make_targets = lambda lst: ",".join(str(id) for id in lst)
  34.  
  35. def __init__(self, *pargs):
  36. try:
  37. self.token, self.my_id, self.api_v, self.max_workers = pargs
  38. self.my_name, self.my_last_name, self.photo = self.base_info([self.my_id])
  39. self.all_friends, self.count_friends = self.friends(self.my_id)
  40. except VkException as error:
  41. sys.exit(error)
  42.  
  43. def request_url(self, method_name, parameters, access_token=False):
  44. """read https://vk.com/dev/api_requests"""
  45.  
  46. req_url = 'https://api.vk.com/method/{method_name}?{parameters}&v={api_v}'.format(
  47. method_name=method_name, api_v=self.api_v, parameters=parameters)
  48.  
  49. if access_token:
  50. req_url = '{}&access_token={token}'.format(req_url, token=self.token)
  51.  
  52. return req_url
  53.  
  54. def base_info(self, ids):
  55. """read https://vk.com/dev/users.get"""
  56. r = requests.get(self.request_url('users.get', 'user_ids=%s&fields=photo' % (','.join(map(str, ids))))).json()
  57. if 'error' in r.keys():
  58. raise VkException('Error message: %s Error code: %s' % (r['error']['error_msg'], r['error']['error_code']))
  59. r = r['response'][0]
  60. # Проверяем, если id из settings.py не деактивирован
  61. if 'deactivated' in r.keys():
  62. raise VkException("User deactivated")
  63. return r['first_name'], r['last_name'], r['photo']
  64.  
  65. def friends(self, id):
  66. """
  67. read https://vk.com/dev/friends.get
  68. Принимает идентификатор пользователя
  69. """
  70. # TODO: слишком много полей для всего сразу, город и страна не нужны для нахождения общих друзей
  71. r = requests.get(self.request_url('friends.get',
  72. 'user_id=%s&fields=uid,first_name,last_name,photo,country,city,sex,bdate' % id)).json()['response']
  73. #r = list(filter((lambda x: 'deactivated' not in x.keys()), r['items']))
  74. return {item['id']: item for item in r['items']}, r['count']
  75.  
  76. def common_friends(self):
  77. """
  78. read https://vk.com/dev/friends.getMutual and read https://vk.com/dev/execute
  79. Возвращает в словаре кортежи с инфой о цели и списком общих друзей с инфой
  80. """
  81. result = []
  82. # разбиваем список на части - по 25 в каждой
  83. for i in VkFriends.parts(list(self.all_friends.keys())):
  84. r = requests.get(self.request_url('execute.getMutual',
  85. 'source=%s&targets=%s' % (self.my_id, VkFriends.make_targets(i)), access_token=True)).json()['response']
  86. for x, id in enumerate(i):
  87. result.append((self.all_friends[int(id)], [self.all_friends[int(i)] for i in r[x]] if r[x] else None))
  88.  
  89. return result
  90.  
  91. def deep_friends(self, deep):
  92. """
  93. Возвращает словарь с id пользователей, которые являются друзьями, или друзьями-друзей (и т.д. в зависимсти от
  94. deep - глубины поиска) указаннного пользователя
  95. """
  96. result = {}
  97.  
  98. @force
  99. def worker(i):
  100. r = requests.get(self.request_url('execute.deepFriends', 'targets=%s' % VkFriends.make_targets(i), access_token=True)).json()['response']
  101. for x, id in enumerate(i):
  102. result[id] = tuple(r[x]["items"]) if r[x] else None
  103.  
  104. def fill_result(friends):
  105. with ThreadPoolExecutor(max_workers=self.max_workers) as pool:
  106. [pool.submit(worker, i) for i in VkFriends.parts(friends)]
  107.  
  108. for i in range(deep):
  109. if result:
  110. # те айди, которых нет в ключах + не берем id:None
  111. fill_result(list(set([item for sublist in result.values() if sublist for item in sublist]) - set(result.keys())))
  112. else:
  113. fill_result(requests.get(self.request_url('friends.get', 'user_id=%s' % self.my_id, access_token=True)).json()['response']["items"])
  114.  
  115. return result
  116.  
  117. def from_where_gender(self):
  118. """
  119. Возвращает кортеж из 3х частей
  120. 0 - сколько всего/в% друзей в определнной локации (country, city)
  121. 1 - список, содержащий количество друзей того или иного пола. Где индекс
  122. 0 - пол не указан
  123. 1 - женский;
  124. 2 - мужской;
  125. 2 - сколько друзей родилось в тот или иной день
  126. """
  127. locations, all, genders, bdates = [{}, {}], [0, 0], [0, 0, 0], {}
  128.  
  129. def calculate(dct, all):
  130. return {k: (dct[k], round(dct[k]/all * 100, 2)) for k, v in dct.items()}
  131.  
  132. def constr(location, dct, ind):
  133. if location in dct.keys():
  134. place = dct[location]["title"]
  135. locations[ind][place] = 1 if place not in locations[ind] else locations[ind][place] + 1
  136. all[ind] += 1
  137.  
  138. for i in self.all_friends.values():
  139. constr("country", i, 0)
  140. constr("city", i, 1)
  141. if "sex" in i.keys():
  142. genders[i["sex"]] += 1
  143. if "bdate" in i.keys():
  144. date = '.'.join(i["bdate"].split(".")[:2])
  145. bdates[date] = 1 if date not in bdates else bdates[date] + 1
  146.  
  147. return (calculate(locations[0], all[0]), calculate(locations[1], all[1])), genders, bdates
  148.  
  149. @staticmethod
  150. def save_load_deep_friends(myfile, sv, smth=None):
  151. if sv and smth:
  152. pickle.dump(smth, open(myfile, "wb"))
  153. else:
  154. return pickle.load(open(myfile, "rb"))
  155.  
  156. if __name__ == '__main__':
  157. a = VkFriends(token, my_id, api_v, max_workers)
  158. print(a.my_name, a.my_last_name, a.my_id, a.photo)
  159. #print(a.common_friends())
  160. df = a.deep_friends(deep)
  161. print(df)
  162. VkFriends.save_load_deep_friends('deep_friends_dct', True, df)
  163. #print(pickle.load( open('deep_friends_dct', "rb" )))
  164. #print(a.from_where_gender())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement