def db_create_table(db=None, table_name='tracks'): try: statement = f""" CREATE TABLE IF NOT EXISTS {table_name} ( id TEXT UNIQUE PRIMARY KEY, name TEXT NOT NULL, artist1 TEXT NOT NULL, artist1ID TEXT NOT NULL, artist2 TEXT, artist2ID TEXT, popularity INTEGER NOT NULL, liked BOOLEAN NOT NULL, acousticness DECIMAL(1, 5) NOT NULL, danceability DECIMAL(1, 5) NOT NULL, duration_ms INTEGER NOT NULL, energy DECIMAL(1, 5) NOT NULL, instrumentalness DECIMAL(1, 5) NOT NULL, key INTEGER NOT NULL, liveness DECIMAL(1, 5) NOT NULL, loudness INTEGER NOT NULL, mode INTEGER NOT NULL, speechiness DECIMAL(1, 5) NOT NULL, valence DECIMAL(1, 5) NOT NULL, tempo INTEGER NOT NULL, time_signature INTEGER NOT NULL ); """ cursor = db.cursor() cursor.execute(statement) db.commit() except Error as e: print('Error: ' + str(e), color='red')
def db_create_connection(db_file): try: connection = sqlite3.connect(db_file) return connection except Error as e: print('Error: ' + str(e), color='red') return None
def notify(row, url, sender, recipient, password, width=64): p2 = ProgressBar(name='Deal Found!', steps=5, width=width, completion='Email Sent to {}'.format(recipient)) smtp_server = 'smtp.gmail.com' port = 587 p2.update(step_name='Creating Secure SSL Connection') context = ssl.create_default_context() p2.update(step_name='Preparing Message') data = row.iloc[0, :].to_dict() message = MIMEMultipart('alternative') message['Subject'] = f'The price of an item you\'re following fell!' message["From"] = sender message['To'] = recipient plain_text = (f"Item: {data['Item']}" f"Total: {data['Total']}" f"Condition: {data['Condition']}" f"Seller: {data['Seller']}, {data['Location']}" f"URL: {url}" f"\nBe sure to select the seller show above :)") html_text = ( f"<html><body><p>" f"<strong>Item: </strong>{data['Item']}" f"<br><strong>Total: </strong>{data['Total']}" f"<br><strong>Condition: </strong>{data['Condition']}" f"<br><strong>Seller: </strong>{data['Seller']}, {data['Location']}" f"<br><strong>URL: </strong>{url}" f"<br><br>Be sure to select the seller show above :)" f"</p></body></html>") message.attach(MIMEText(plain_text, 'plain')) message.attach(MIMEText(html_text, 'html')) try: p2.update(step_name='Connecting to Email Server') server = SMTP(smtp_server, port) server.ehlo() server.starttls(context=context) server.ehlo() p2.update(step_name='Logging in to Server') server.login(sender, password) p2.update(step_name='Sending Notification') server.sendmail(sender, recipient, message.as_string()) except Exception as e: print(e, color='red') finally: server.quit()
def db_insert_entry(connection, entry): try: statement = """ INSERT INTO prices (datetime, item, total, seller) VALUES(?, ?, ?, ?); """ cursor = connection.cursor() cursor.execute(statement, entry) connection.commit() return cursor.lastrowid except Error as e: print('Error: ' + str(e), color='red')
def db_insert_track(db=None, track=None): try: statement = """ INSERT INTO tracks (id, name, artist1, artist1ID, artist2, artist2ID, popularity, liked, acousticness, danceability, duration_ms, energy, instrumentalness, key, liveness, loudness, mode, speechiness, valence, tempo, time_signature) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); """ cursor = db.cursor() cursor.execute(statement, track) db.commit() return cursor.lastrowid except Error as e: print('Error: ' + str(e), color='red')
def db_get_all(db=None): try: statement = """ SELECT * FROM tracks """ cursor = db.cursor() cursor.execute(statement) rows = cursor.fetchall() return rows except Error as e: print('Error: ' + str(e), color='red')
def db_select_track(db=None, liked=None): try: statement = """ SELECT * FROM tracks WHERE liked = ? """ cursor = db.cursor() cursor.execute(statement, (liked,)) rows = cursor.fetchall() return rows except Error as e: print('Error: ' + str(e), color='red')
def db_create_table(connection): try: statement = """ CREATE TABLE IF NOT EXISTS prices ( id INTEGER PRIMARY KEY AUTOINCREMENT, datetime DATETIME NOT NULL, item TEXT NOT NULL, total DECIMAL(30, 2) NOT NULL, seller TEXT NOT NULL ); """ cursor = connection.cursor() cursor.execute(statement) connection.commit() except Error as e: print('Error: ' + str(e), color='red')
def db_select_item(connection, item): try: last_week = (datetime.now() - timedelta(7)).strftime('%Y-%m-%d %H:%M:%S') today = datetime.now().strftime('%Y-%m-%d %H:%M:%S') statement = """ SELECT AVG(total), MIN(total) FROM prices WHERE item=? AND datetime >= ? and datetime <= ? """ cursor = connection.cursor() cursor.execute(statement, (item, last_week, today)) rows = cursor.fetchall() return (round(Decimal(rows[0][0]), 2), rows[0][1]) except Error as e: print('Error: ' + str(e), color='red')
def scrape(url, p=None): p.update(step_name='Requesting Data from Amazon.com') response = requests.get(url, headers=headers) if response.status_code == 403: print("403", color='red') else: rows = [] p.update(step_name='Gathering Data') soup = BeautifulSoup(response.text, 'lxml') listings = soup.find_all("div", 'a-row a-spacing-mini olpOffer', limit=99) p.update(step_name='Scraping Listings') for listing in listings: price = listing.find('span', 'a-color-price').string.strip() price = Decimal(price.replace('$', '')) ship_price = 0 if listing.find('span', 'olpShippingPrice'): ship_price = listing.find('span', 'olpShippingPrice').string.strip() ship_price = Decimal(ship_price.replace('$', '')) total = price + ship_price condition = listing.find('span', 'olpCondition').string.strip() delivery = listing.find('div', 'olpDeliveryColumn').find('span', 'a-list-item').string.strip() \ .replace('.', '') \ .replace('United States', 'US') \ .replace('Ships from ', '') seller = listing.find('h3', 'olpSellerName').find('a').text.strip() seller = re.sub('[^0-9a-zA-Z ]+', '*', seller) rating = listing.find( 'div', 'olpSellerColumn').find('b').string.strip().replace( ' positive', '') row = { 'Item': asin, 'Total': total, 'Price': price, 'Shipping': ship_price, 'Condition': condition, 'Seller': seller, 'Location': delivery, 'Seller Rating': rating } rows.append(row) df = pd.DataFrame(rows, columns=[ 'Item', 'Total', 'Price', 'Shipping', 'Condition', 'Seller', 'Location', 'Seller Rating' ]) df = df.sort_values(by=['Item', 'Total'], ascending=[1, 1]) return df.head(3)
parser.add_argument('interval', help='How many minutes there are between iterations') # TODO: better decision making # TODO: handle and track multiple items # TODO: hide this error, then split these up and make util try: args = parser.parse_args() asin = args.asin condition = args.condition shipping = args.shipping recipient = args.email interval = float(args.interval) except SystemExit as e: print() asin = input('Enter Item\'s ASIN: ', default='B075HRTD2C', color='yellow') condition = input('Enter Condition: ', options=condition_options.keys(), default='all', color='yellow') shipping = input('Enter Shipping Constraint: ', options=shipping_options.keys(), default='all', color='yellow') recipient = input('Enter Your Email: ', default='*****@*****.**', color='yellow') interval = float(
def main(playlist_length, username, client_id, client_secret, redirect_uri, width=8): p1 = ProgressBar('Gathering Your Liked and Disliked Songs', steps=5, width=width, completion='Songs Gathered') p1.update(step_name='Connecting to Spotify') SPConnection().set_all(username, client_id, client_secret) # SPConnection().get_connection() p1.update(step_name='Connecting to the Database') connection = db_create_connection('records.db') db_create_table() p1.update(step_name='Collecting Your Saved Tracks') load_saved_tracks() p1.update(step_name='Collecting Your Disliked Tracks') load_playlist_tracks(playlist_id='6sd1N50ZULzrgoWX0ViDwC', liked=0) p1.update(step_name='Pulling Track Details from the Database') all_tracks = db_get_all() data = pd.DataFrame(all_tracks, columns=['id','name','artist1','artist1ID','artist2','artist2ID','popularity','liked','danceability','duration_ms','energy','key','loudness','mode','speechiness','acousticness','instrumentalness','liveness','valence','tempo','time_signature']) print(data.head()) # ---------------------------------------------------------------- p2 = ProgressBar('Decision Tree Classifier', steps=3, width=width, completion='Classifier Trained') train, test = train_test_split(data, test_size=0.15) p2.update(step_name='Building Tree') tree = DecisionTreeClassifier(min_samples_split=100) data_features = ['popularity', 'danceability', 'energy', 'key', 'loudness', 'mode', 'speechiness', 'acousticness', 'instrumentalness', 'liveness', 'valence', 'tempo', 'duration_ms', 'time_signature'] x_train = train[data_features] y_train = train['liked'] x_test = test[data_features] y_test = test['liked'] p2.update(step_name=f'Training Tree with {len(train)} samples') dt = tree.fit(x_train, y_train) p2.update(step_name=f'Testing Tree with {len(test)} samples') y_pred = tree.predict(x_test) score = accuracy_score(y_test, y_pred) * 100 print(f'Decision Tree Accuracy: {round(score, 2)}') # ---------------------------------------------------------------- p3 = ProgressBar('Generating Recommendations', steps=4, width=width, completion='Daily Playlist Created') p3.update(step_name='Gathering a Variety of Songs') new_tracks = get_recommendations(data=data) # ---------------------------------------------------------------- date = datetime.strftime(datetime.now(), '%m/%d') playlist_title = f'Discover Daily {date}' p3.update(step_name=f'Creating Playlist {playlist_title}') playlist_description = f"Generated {str(date)} by Noah Tigner's Recommender Engine" playlist_id = create_playlist(title=playlist_title, description=playlist_description) # ---------------------------------------------------------------- p3.update(step_name='Testing the Songs With the Classifier') t = pd.DataFrame(new_tracks) pred = t[data_features] predictions = tree.predict(pred) chosen = [] for i in range(len(predictions)): if predictions[i] == 1: chosen.append(t.iloc[i]['id']) playlist_length = min([playlist_length, len(chosen) - 1, 100]) p3.update(step_name=f'Filling the Playlist with {playlist_length} songs you might like') choices = random.sample(chosen, k=playlist_length) playlist_add_tracks(playlist_id=playlist_id, tracks=choices)
playlist_length = min([playlist_length, len(chosen) - 1, 100]) p3.update(step_name=f'Filling the Playlist with {playlist_length} songs you might like') choices = random.sample(chosen, k=playlist_length) playlist_add_tracks(playlist_id=playlist_id, tracks=choices) if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('playlist_length', help='Number of Tracks to Generate') try: args = parser.parse_args() playlist_length = int(args.playlist_length) except SystemExit as e: print() playlist_length = int(input('Enter The Number of Tracks to Generate: ', default=25, color='yellow')) try: username = os.environ['SPOTIPY_USERNAME'] client_id = os.environ['SPOTIPY_CLIENT_ID'] client_secret = os.environ['SPOTIPY_CLIENT_SECRET'] redirect_uri = os.environ['SPOTIPY_REDIRECT_URI'] except KeyError: print(f"In the future, consider setting the following up as environment variables.\nSee: https://spotipy.readthedocs.io/en/latest/#authorization-code-flow", color='red') username = input('Enter your Spotify username: '******'yellow') client_id = input('Enter your Spotify Client ID: ', color='yellow') client_secret = input('Enter your Spotify Client Secret: ', color='yellow') redirect_uri = input('Enter your Redirect URI: ', color='yellow') main(playlist_length, username, client_id, client_secret, redirect_uri, width=8)