Skip to content

Commit 0f1bc1d

Browse files
authored
Merge pull request #768 from Mansi-Binjola/issue-647-creating-tkinter-song-scraper-GUI
Added song_scraper_GUI file
2 parents 0d8b51b + 84e30e4 commit 0f1bc1d

12 files changed

+353
-0
lines changed

song_scraper_GUI/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Find My Tune
2+
Find My Tune is a GUI that helps you find and download your favorite songs.
3+
4+
## Requirements
5+
```
6+
python3
7+
pip3
8+
Tkinter
9+
selenium chrome driver
10+
Selenium
11+
```
12+
13+
## Instruction For Use
14+
1. run requirements.txt
15+
16+
`pip3 -r install requirements.txt`
17+
18+
2. run the `findMyTune.py` file using the command
19+
20+
`python3 findMyTune.py`
21+
3. Find my Tune is opened, on the search box enter your song name with artist name<sup>1</sup>.
22+
![start window image](./screenshots/open_window_screenshot.png)
23+
4. Searching the song may take some time, so be patient.
24+
![search window image](./screenshots/search_song_download_screenshot.png)
25+
5. After the results are shown select any one of the results using the cursor.
26+
![search window image](./screenshots/search_song_download_screenshot.png)
27+
6. Click on the download button and wait for the results.
28+
7. Voila! your song is download and is saved inside the downloads folder.
29+
![song downloaded image](./screenshots/song_downloaded_screenshot.png)
30+
8. Use the refresh button to clear the results.
31+
9. Steps to use the application and notes are provided in the help window.
32+
![help window image](./screenshots/help_window_screenshot.png)
33+
34+
### AUTHOR
35+
Code written by [Mansi Binjola](https://linktr.ee/MansiBinjola)
36+
37+
### DISCLAIMER
38+
1. Make sure there is no spelling mistake in your search, as sometimes it doesn't find the song correctly.
39+
2. There are chances that the song may not be downloaded, so please restart the interface.
40+
3. The song scraper that I have made can only download a file that is less than 5 min. If you want to download a file that is of big size, simply comment line number 69 of `mp3Clan_top_web_scraper.py`.
41+
42+
`driver.set_page_load_timeout(20)`

song_scraper_GUI/findMyTune.py

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
from tkinter import Tk, Button, Toplevel, Label, Frame, PhotoImage, Entry
2+
from tkinter import TOP, LEFT, RIGHT, NE, W, DISABLED, NORMAL, YES
3+
from tkinter import CENTER, BOTH
4+
from tkinter import ttk
5+
import tkinter.messagebox
6+
import os
7+
from mp3Clan_top_web_scraper import findMySong, downloadMySong
8+
9+
10+
class SongGUI:
11+
def __init__(self, root):
12+
self.root = root
13+
self.root.title('Find my tune')
14+
self.root.geometry()
15+
self.root.minsize(800, 800)
16+
self.searchname = tkinter.StringVar()
17+
18+
# creating help button
19+
help_button_img = PhotoImage(file='images/help_button.png')
20+
help_button_img = help_button_img.subsample(2)
21+
help_img_label = Label(image=help_button_img)
22+
help_img_label.image = help_button_img
23+
self.help_button = Button(self.root,
24+
image=help_button_img,
25+
command=self.helpFrame,
26+
border=0)
27+
self.help_button.pack(side=TOP, anchor=NE, padx=10, pady=10)
28+
29+
# creating input frame
30+
self.input_frame = Frame(self.root)
31+
self.input_frame.pack()
32+
33+
# creating heading
34+
heading = Label(self.input_frame, text="Find My Tune",
35+
font=("Helvetica", 30), fg="black")
36+
heading.pack(pady=20, side=TOP)
37+
38+
# creating search bar
39+
self.search_box_input = Entry(self.input_frame, font=(
40+
"Helvetica", 20), textvariable=self.searchname)
41+
self.search_box_input.pack()
42+
43+
# creating search button
44+
search_button_img = PhotoImage(file='images/search_button.png')
45+
search_button_img = search_button_img.subsample(2)
46+
search_img_label = Label(image=search_button_img)
47+
search_img_label.image = search_button_img
48+
self.search_button = Button(self.input_frame, image=search_button_img,
49+
border=0, command=self.searchSong)
50+
self.search_button.pack(pady=10, side=LEFT)
51+
52+
# creating refresh button
53+
refresh_button_img = PhotoImage(file='images/refresh_button.png')
54+
refresh_button_img = refresh_button_img.subsample(2)
55+
refresh_img_label = Label(image=refresh_button_img)
56+
refresh_img_label.image = refresh_button_img
57+
self.refresh_button = Button(self.input_frame,
58+
image=refresh_button_img,
59+
fg='green',
60+
command=self.refreshFrame,
61+
border=0)
62+
self.refresh_button.pack(pady=10, side=RIGHT)
63+
64+
def helpFrame(self):
65+
'''shows help Window in new frame'''
66+
67+
self.help_button['state'] = DISABLED
68+
# Toplevel object which will be treated as a new window
69+
self.help_window = Toplevel(self.root)
70+
71+
# sets the title of the Toplevel widget
72+
self.help_window.title("Help Window")
73+
74+
# sets the geometry of toplevel
75+
self.help_window.geometry("550x800")
76+
77+
# making help_window unresizable
78+
self.help_window.resizable(0, 0)
79+
80+
# reading content from help_window.txt
81+
info_file = open("help_window.txt")
82+
lines = info_file. readlines()
83+
84+
heading = Label(self.help_window, font=(
85+
"Helvetica 20 underline"), text="HELP WINDOW")
86+
heading.pack(side=TOP, padx=10, pady=10)
87+
88+
# code, to show content in help_window
89+
Label(self.help_window, wraplength=500, justify="left", font=("", 12),
90+
text=lines[0]).pack(side=TOP, pady=10, padx=5)
91+
Label(self.help_window, font=("Helvetica 16 underline bold"),
92+
text="INSTRUCTIONS").pack(anchor=W, padx=10, pady=10)
93+
94+
for i in range(1, 9):
95+
Label(self.help_window, wraplength=500,
96+
justify="left", font=("", 12),
97+
text=str(i) + ". " + lines[i]).pack(anchor=W, pady=2, padx=10)
98+
Label(self.help_window, font=("Helvetica 16 underline"),
99+
text="NOTE").pack(anchor=W, padx=10, pady=10)
100+
for i in range(8, 11):
101+
Label(self.help_window, wraplength=500,
102+
justify="left", font=("", 12),
103+
text=str(i - 7) + ". " + lines[i]).pack(anchor=W, pady=2, padx=10)
104+
105+
self.help_window.protocol("WM_DELETE_WINDOW", self.close_window)
106+
107+
def close_window(self):
108+
'''function which closes the help_window'''
109+
self.help_window.destroy()
110+
self.help_button['state'] = NORMAL
111+
112+
def searchSong(self):
113+
''''function reads the search_input and searchs for the song'''
114+
self.songname = self.searchname.get()
115+
self.searchname.set('')
116+
117+
# if the search box is not empty
118+
if(self.songname):
119+
120+
self.songlist = findMySong(self.songname)
121+
self.search_button['state'] = DISABLED
122+
self.searchname.set('')
123+
self.result_frame = Frame(self.root)
124+
self.result_frame.pack()
125+
self.results = ttk.Treeview(self.result_frame)
126+
127+
# if search is not empty
128+
if(self.songlist):
129+
130+
# creates four cols, 1 phantom columns
131+
self.results['columns'] = ('S.NO', 'Name', 'Duration')
132+
133+
style = ttk.Style()
134+
style.configure("Treeview", rowheight=18, columns=30000)
135+
136+
self.results.column("#0", stretch=YES, width=0, minwidth=0)
137+
self.results.column("S.NO", stretch=YES, anchor=W, width=40)
138+
self.results.column("Name", anchor=W, stretch=YES, width=600)
139+
self.results.column(
140+
"Duration", stretch=YES, anchor=W, width=80)
141+
142+
# Create Headings
143+
self.results.heading("S.NO", text="S.NO", anchor=W)
144+
self.results.heading("Name", text="Name", anchor=CENTER)
145+
self.results.heading("Duration", text="Duration", anchor=W)
146+
147+
self.results.pack(pady=10, expand=1, fill=BOTH)
148+
for i in range(len(self.songlist)):
149+
self.results.insert(parent='', index='end', iid=i, text='',
150+
values=(str(i + 1),
151+
self.songlist[i]['title'],
152+
self.songlist[i]['duration']))
153+
154+
self.down_button = Button(
155+
self.result_frame, text='DOWNLOAD',
156+
fg='white', bg='green',
157+
command=self.downloadSong)
158+
self.down_button.pack(padx=10, side=TOP)
159+
160+
else:
161+
tkinter.messagebox.showerror(
162+
'No Song Foumd',
163+
"Could'nt find your song, please try again")
164+
self.search_button['state'] = NORMAL
165+
166+
else:
167+
tkinter.messagebox.showerror(
168+
'Search box Empty', "Please enter song name")
169+
self.search_button['state'] = NORMAL
170+
171+
def downloadSong(self):
172+
'''Function which download the song'''
173+
174+
self.down_button['state'] = DISABLED
175+
songNumber = self.results.focus()
176+
177+
# if option is selected
178+
if(songNumber):
179+
songNumber = int(songNumber)
180+
downloadMySong(self.songlist[songNumber]['download-link'])
181+
filename = [f for f in os.listdir() if f.endswith('.mp3')]
182+
if(filename):
183+
# rename file and save in download folder
184+
os.rename(filename[0], 'downloads/' + filename[0][:-14] + ".mp3")
185+
tkinter.messagebox.showinfo(
186+
'Song Downloaded Successfully',
187+
"Your song is downloaded.")
188+
else:
189+
tkinter.messagebox.showerror(
190+
'Song Not Downloaded',
191+
"Could'nt download your song, please try again later.")
192+
filename = [f for f in os.listdir(
193+
) if f.endswith('.crdownload')]
194+
if(filename):
195+
for file in filename:
196+
os.remove(file)
197+
else:
198+
tkinter.messagebox.showerror(
199+
'Song Not Selected',
200+
"Please choose one item from list, then press download button")
201+
self.down_button['state'] = NORMAL
202+
203+
def refreshFrame(self):
204+
'''clears the search window'''
205+
self.search_button['state'] = NORMAL
206+
self.searchname.set('')
207+
try:
208+
self.result_frame. pack_forget()
209+
except AttributeError:
210+
tkinter.messagebox.showinfo(
211+
'Already Refreshed',
212+
"window already refreshed")
213+
214+
215+
if(__name__ == "__main__"):
216+
root = Tk()
217+
SongGUI(root)
218+
root.mainloop()

song_scraper_GUI/help_window.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Find My Tune is a GUI that helps you find and download your favorite songs.
2+
To search for your song, write the song name and artist name in the search bar and click on the search button (green button).
3+
Wait some time, since searching songs some takes time.
4+
Now select the song which you want to download.
5+
Now, below will be given a download button. Click it.
6+
If the window is frozen, wait a minute. Since downloading a file takes time.
7+
A pop-up will appear if the song is download or not.
8+
Congrats, your favorite song is downloaded and safely saved inside the downloads folder.
9+
Use refresh button to refresh/clear the window.
10+
For better search results, enter the name of the song, then the name of the artist.
11+
If the application is frozen or not searching or not downloading after multiple attempts, kindly restart the application.
12+
This application works better for downloading songs that are of time 5 min or lesser.
10 KB
Loading
13.4 KB
Loading
17.2 KB
Loading
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from selenium import webdriver
2+
from webdriver_manager.chrome import ChromeDriverManager
3+
from selenium.common.exceptions import NoSuchElementException, TimeoutException
4+
import time
5+
from selenium.webdriver.chrome.options import Options
6+
7+
8+
def findMySong(song_name):
9+
'''
10+
function which accepts string and returns list of 10 available songs
11+
'''
12+
options = Options()
13+
options.headless = True
14+
15+
driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
16+
driver.get("http://mp3clan.top/mp3/")
17+
18+
search_box = driver.find_elements_by_xpath('.//*[@id="search-orange"]')
19+
search_box[0].send_keys(song_name)
20+
search_box[0].click()
21+
22+
button = driver.find_element_by_class_name("searchClan-button-left")
23+
button.click()
24+
25+
time.sleep(10)
26+
27+
try:
28+
songs = driver.find_elements_by_class_name('mp3list-table')
29+
song_list = []
30+
cnt = 0
31+
for song in songs:
32+
try:
33+
if(cnt < 10):
34+
details = song.find_element_by_class_name(
35+
"mp3list-play").text
36+
details = details.split("\n")
37+
link_sel_obj = song.find_element_by_tag_name("a")
38+
link = link_sel_obj.get_attribute("href")
39+
link = link[:33] + "get" + link[37:]
40+
if(len(details) > 2):
41+
vid_item = {
42+
'title': details[0],
43+
"duration": details[-1],
44+
"download-link": link
45+
}
46+
song_list.append(vid_item)
47+
cnt += 1
48+
else:
49+
break
50+
except NoSuchElementException:
51+
print("no files found")
52+
continue
53+
except NoSuchElementException:
54+
print("big error")
55+
driver.close()
56+
return(song_list)
57+
58+
59+
def downloadMySong(url):
60+
'''
61+
function which accepts url,
62+
and download's and save song in current directory
63+
'''
64+
try:
65+
options = Options()
66+
options.headless = True
67+
68+
driver = webdriver.Chrome(
69+
ChromeDriverManager().install(), options=options)
70+
driver.set_page_load_timeout(20)
71+
72+
driver.get(url)
73+
driver.get(url)
74+
75+
time.sleep(10)
76+
driver.close()
77+
except TimeoutException:
78+
print("session timeout")
79+
driver.close()

song_scraper_GUI/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
selenium
2+
tk
Loading
Loading

0 commit comments

Comments
 (0)