#! /usr/bin/env python import sys from contextlib import contextmanager sys.path.insert(0, '.') from datetime import datetime import time import requests from pymysql.cursors import Cursor import pymysql from tracker import soundcloud from tracker.youtube import youtube from tracker.config import _get_secret_json import traceback unicron_conf_dict = _get_secret_json('unicronSecretsProd') mysql_kwargs = dict( host=unicron_conf_dict['UC_MYSQL_HOST'], user='unicron', password=unicron_conf_dict['UC_MYSQL_PASSWORD'], db='unicron', charset='utf8mb4', # cursorclass='DictCursor' ) @contextmanager def commit_after() -> Cursor: connection = pymysql.connect(**mysql_kwargs) try: with connection.cursor() as cur: yield cur connection.commit() finally: try: connection.close() except Exception as e: print("Warning, failed to close connection") print(e) def capture_soundcloud(): track1 = 572735187 track2 = 628340139 try: data1, data2 = list(sorted( soundcloud.client.get("/tracks", limit=5, ids=",".join([str(i) for i in (track1, track2)])), key=lambda r: r.id )) except Exception as e: print(f"Failed to fetch soundcloud data {e}") traceback.print_exc() sql = ''' insert into deathbed_sc_plays (ts, plays_1, plays_2, comments_1, comments_2, views_1, views_2) values (%s, %s, %s, %s, %s, %s, %s) ''' args = ( datetime.utcnow().isoformat(), data1.playback_count, data2.playback_count, data1.comment_count, data2.comment_count, data1.favoritings_count, data2.favoritings_count, ) with commit_after() as cur: print("Recording soundcloud", args) cur.execute(sql, args) def capture_youtubes(): ytid1 = 'GgCNdUmsDYE' ytid2 = '4eaXoebXKfY' ytid3 = 'hNqdxGsbQsA' all_ytids = [ytid1, ytid2, ytid3] try: item1, item2, item3 = list(sorted( youtube._fetch_video_stats(video_ids=all_ytids)['items'], key=lambda x: all_ytids.index(x['id']) )) except Exception as e: print(f"Failed to fetch youtube data {e}") traceback.print_exc() sql = ''' insert into deathbed_youtubes (ts, views1, views2, views3, likes1, likes2, likes3, dislikes1, dislikes2, dislikes3, comments1, comments2, comments3) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ''' args = ( datetime.utcnow().isoformat(), item1['statistics']['viewCount'], item2['statistics']['viewCount'], item3['statistics']['viewCount'], item1['statistics']['likeCount'], item2['statistics']['likeCount'], item3['statistics']['likeCount'], item1['statistics']['dislikeCount'], item2['statistics']['dislikeCount'], item3['statistics']['dislikeCount'], item1['statistics']['commentCount'], item2['statistics']['commentCount'], item3['statistics']['commentCount'] ) with commit_after() as cur: print("Recording youtube", args) cur.execute(sql, args) def capture_tiktoks(): tiktokurl = 'https://www.tiktok.com/music/death-bed-feat-beabadoobee-6703427142346083074' video_count = _scrape_video_count(tiktokurl) if video_count is None: print("Warning: TikToks cannot be saved.") sql = ''' insert into deathbed_tiktoks (ts, videos) values (%s, %s) ''' args = (datetime.utcnow().isoformat(), video_count) with commit_after() as cur: print("Recording tiktoks", args) cur.execute(sql, args) def main_loop(scrape_period_seconds): starttime = time.time() while True: capture_soundcloud() capture_youtubes() capture_tiktoks() time.sleep(scrape_period_seconds - ((time.time() - starttime) % scrape_period_seconds)) import json from bs4 import BeautifulSoup def _scrape_video_count(url): req = requests.get(url, headers={'User-Agent': 'chrome'}) try: if url not in req.url: raise RuntimeError(f"Not on expected page, url {req.url}, {req.status_code}, {req.reason}") soup = BeautifulSoup(req.content, 'html5lib') num_toks = int(next(filter(None, [json.loads(d.text).get('props',{}).get('pageProps') for d in soup.select('script[type*="json"]')])).get('musicData', {}).get('posts')) except Exception as e: print(f"Failed to get number of tiktoks {e}") import traceback traceback.print_exc() return None else: return num_toks if __name__ == '__main__': scrape_period_seconds = 20.0*60.0 print(f"Launching powfu getter, every {scrape_period_seconds} seconds") main_loop(scrape_period_seconds)