Advertisement
kasougi

Untitled

May 28th, 2021
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.35 KB | None | 0 0
  1. import requests
  2. import json
  3. from bs4 import BeautifulSoup, Comment
  4. import time
  5. import random
  6. import dataset
  7. from datetime import date
  8.  
  9.  
  10. def restruct(item):
  11.     """
  12.    Раскрывает нужные вложенности
  13.    :param item: dict
  14.    :return: dict
  15.    """
  16.     dow = item['downloads_and_revenue']['downloads']
  17.     rev = item['downloads_and_revenue']['revenue']
  18.  
  19.     def get_num(item):
  20.         if item:
  21.             num = ''
  22.             for word in item:
  23.                 try:
  24.                     num += str(int(word))
  25.                 except ValueError:
  26.                     pass
  27.             num = int(num)
  28.             if item[-1] == 'b':
  29.                 num *= 1000000000
  30.             elif item[-1] == 'm':
  31.                 num *= 1000000
  32.             elif item[-1] == 'k':
  33.                 num *= 1000
  34.             return num
  35.         return None
  36.  
  37.     def get_gen(item):
  38.         if item:
  39.             if item[0] in ['>', '<']:
  40.                 return item[0]
  41.         return None
  42.  
  43.     rev_break = item['downloads_and_revenue']['revenueBreakdown']
  44.     dow_break = item['downloads_and_revenue']['downloadBreakdown']
  45.     release_date = date(year=int(item['release_date'][0:4]), month=int(item['release_date'][5:7]),
  46.                         day=int(item['release_date'][8:10]))
  47.  
  48.     updated_date = date(year=int(item['updated_date'][0:4]), month=int(item['updated_date'][5:7]),
  49.                         day=int(item['updated_date'][8:10]))
  50.  
  51.     downloads_revenue_date = date(year=int(item['downloads_revenue_date'][0:4]),
  52.                                   month=int(item['downloads_revenue_date'][5:7]),
  53.                                   day=int(item['downloads_revenue_date'][8:10]))
  54.  
  55.     if item['worldwide_release_date']:
  56.         worldwide_release_date = date.fromtimestamp(int(str(item['worldwide_release_date'])[:10]))
  57.     else:
  58.         worldwide_release_date = None
  59.     if item['recent_release_date']:
  60.         recent_release_date = date.fromtimestamp(int(str(item['recent_release_date'])[:10]))
  61.     else:
  62.         recent_release_date = None
  63.     if item['content_rating']:
  64.         content_rating = int(item['content_rating'][:len(item['content_rating']) - 1])
  65.     item.pop('id')
  66.     item.pop('short_description')
  67.     item.pop('game_intel_data')
  68.     item.pop('publisher_address')
  69.     item.pop('publisher_email')
  70.     item.pop('publisher_apps')
  71.     item.pop('unified_app')
  72.     item.pop('contains_ads')
  73.     item.pop('installs')
  74.     item.pop('downloads_and_revenue')
  75.     item.pop('humanized_worldwide_last_month_downloads')
  76.     item.pop('humanized_worldwide_last_month_revenue')
  77.     item.pop('top_in_app_purchases')
  78.     item.pop('related_apps')
  79.     item.pop('appId')
  80.     item.update(
  81.         {
  82.             'id': item['app_id'],
  83.             'dow_sign': get_gen(dow),
  84.             'downloads': get_num(dow),
  85.             'rev_sign': get_gen(rev),
  86.             'revenue': get_num(rev),
  87.             'revenue_breakdown': rev_break,
  88.             'download_breakdown': dow_break,
  89.             'is_parsed': 1,
  90.             'release_date': release_date,
  91.             'updated_date': updated_date,
  92.             'downloads_revenue_date': downloads_revenue_date,
  93.             'recent_release_date': recent_release_date,
  94.             'worldwide_release_date': worldwide_release_date,
  95.             'content_rating': content_rating
  96.         })
  97.     item.pop('app_id')
  98.     for key, value in item.items():
  99.         if isinstance(value, dict) or isinstance(value, list):
  100.             item[key] = json.dumps(value)
  101.     return item
  102.  
  103.  
  104. def get_info_from_item(url, db):
  105.     """
  106.    Получает информацию по ссылке
  107.    :param url: str
  108.    :param db: int
  109.    :return: dict
  110.    """
  111.     req_html = requests.get(url)
  112.     soup = BeautifulSoup(req_html.text, 'html.parser')
  113.     # Получаю информацию из комментрация в html
  114.     for comments in soup.findAll(text=lambda text: isinstance(text, Comment)):
  115.         if "'app_profile'," in str(comments).split():
  116.             info = str(comments).split()
  117.             str_for_dict = ''
  118.             for i in info[6:]:
  119.                 str_for_dict += i
  120.             str_for_dict = str_for_dict[1:len(str_for_dict) - 2]
  121.             str_for_dict.replace("'", '"').replace('(', '[').replace(')', ']').replace('{', '[').replace('}', ']')
  122.             info_json = json.loads('{' + str_for_dict + '}')  # парсит json выдает объект dict
  123.             table_sensortower_apps = db['sensortower_apps']
  124.             table_sensortower_iap = db['sensortower_iap']
  125.             table_sensortower_related_apps = db['sensortower_related_apps']
  126.  
  127.             for app_purchases in info_json['top_in_app_purchases']:
  128.                 price_currency = None
  129.                 if app_purchases['price'] == 'Free':
  130.                     app_purchases_price = 0
  131.                 elif app_purchases['price'][0] not in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']:
  132.                     app_purchases_price = float(app_purchases['price'][1:])
  133.                     price_currency = app_purchases['price'][0]
  134.  
  135.                 app_purchases.update({
  136.                     'id': app_purchases['iap_id'],
  137.                     'price': app_purchases_price,
  138.                     'price_currency': price_currency,
  139.                     'sensortower_app_id': info_json['app_id']
  140.                 })
  141.                 app_purchases.pop('iap_id')
  142.                 table_sensortower_iap.upsert(app_purchases, ['id'])
  143.  
  144.             for related_app in info_json['related_apps']:
  145.                 if not table_sensortower_apps.find_one(id=related_app['app_id']):
  146.                     table_sensortower_apps.upsert(
  147.                         {"id": related_app["app_id"], "app_view_url": related_app['app_view_url'], "is_parsed": 0}, ['id'])
  148.                 table_sensortower_related_apps.upsert(
  149.                         {"related_app_id": related_app["app_id"], "sensortower_app_id": info_json["app_id"]}, ['id'])
  150.             # print(f"Парсинг приложения, id: {info_json['app_id']}")
  151.  
  152.             return info_json
  153.  
  154.  
  155. def parse(app_list, db, is_pars_all=1):
  156.     """
  157.    Парсит в цикле.
  158.    Парсер, который в зависимости от параметра 'is_pars_all' парсит либо первые топ-200,
  159.    набирая при этом дополнительную базу из списка 'похожих', либо парсит все добавленные
  160.    в базу неспаршенные ссылки, при этом так же набирая при этом дополнительную базу из
  161.    списка 'похожих'
  162.    :param app_list: dict
  163.    :param db: int
  164.    :param is_pars_all: bool
  165.    :return:
  166.    """
  167.     table_sensortower_apps = db['sensortower_apps']
  168.     for app_item in app_list:
  169.         if table_sensortower_apps.find_one(app_view_url=app_item['app_id'], is_parsed=1):
  170.             continue
  171.         item_for_update = get_info_from_item('https://sensortower.com' + app_item['app_view_url'], db)
  172.         try:
  173.             app_item.update(item_for_update)
  174.         except TypeError:
  175.             print('Ждем разбана')
  176.             time.sleep(random.randint(15, 60))
  177.             continue
  178.         # print(json.dumps(app_item))
  179.         app_item = restruct(app_item)
  180.         table_sensortower_apps.upsert(app_item, ['id'])
  181.         if is_pars_all:
  182.             app_list = table_sensortower_apps.find(is_parsed=0)
  183.         #     print('парсим не топы')
  184.         # else:
  185.         #     print('парсим топы')
  186.  
  187.  
  188. if __name__ == '__main__':
  189.     db = dataset.connect('sqlite:///mydatabase.db')
  190.     table_sensortower_apps = db['sensortower_apps']
  191.     url_top = f'https://sensortower.com/api/ios/rankings/get_category_rankings?category=0&country=US&date=2021-05-11T00%3A00%3A00.000Z&device=IPHONE&limit=200&offset=0'
  192.     top_app_list = []
  193.     for index in range(3):
  194.         top_app_list += [i[index] for i in requests.get(url_top).json()]
  195.     parsed_app_list = table_sensortower_apps.find(is_parsed=1)
  196.     if len({app['id'] for app in top_app_list} & {app['id'] for app in parsed_app_list}) != 600:
  197.         parse(top_app_list, db, 0)
  198.     not_parsed_app_list = table_sensortower_apps.find(is_parsed=0)
  199.     if not not_parsed_app_list:
  200.         not_parsed_app_list = table_sensortower_apps.find(is_parsed=1)
  201.     parse(not_parsed_app_list, db)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement