You may want to display the lyrics while playing a song on iTunes (although the name has changed from Catalina to music). However, it is troublesome to manually search and display the lyrics every time the song changes. Let Python do the tedious work.
(Added on 2020/01/04) It has been improved. → "Let's automatically display the lyrics of the song being played on iTunes in Python (improved version)"
Play a song with the standard Mac app "Music" and automatically display the lyrics on the lyrics site each time the song changes.
OS: macOS Catalina version 10.15 Language: Python 3.6 Library used: appscript, urllib, BeautifulSoup, selenium Each library was installed with PyCharm. I think you can install each with pip.
First, get the song information from the music app. Here we use appscript. I'm not sure about the details, but it seems that AppleScript can be operated with Python. appscript site URL
First, access the app. This time it's music, so it's Music (if you're using Catalina or earlier, it's iTunes).
music = appscript.app("Music")
Next, get the information of the song being played.
name = music.current_track.name.get() #Song title
artist = music.current_track.artist.get() #artist name
album = music.current_track.album.get() #Album name
music_time = music.current_track.time.get() #Song length ("Minutes:Seconds"It is a character string of)
If the length of the song is the same as the character string, it will be troublesome, so change it to the number of seconds. The length of the song is used to determine the change of song.
music_time = music_time.split(":")
music_time = int(music_time[0]) * 60 + int(music_time[1])
Once you have the song information, use it to access the lyrics site. This time, the lyrics site uses Uta-Net. We also use the scraping library BeautifulSoup to access the site. For details on scraping with Beautiful Soup, see "Scraping with Python and Beautiful Soup".
First, use the song title search function on the site to jump to the search result screen. Percent-encode to search for Japanese song titles.
name = parse.quote(name) #Percent encoding
url = "https://www.uta-net.com/search/?Aselect=2&Keyword=" + name + "&Bselect=4&x=0&y=0"
html = request.urlopen(url)
soup = BeautifulSoup(html, "html.parser")
If you jump to the search results, the songs with the same name will appear as a list. If you look at the HTML, the song title and singer name are listed by the a tag in the tr tag, so search for the singer you are looking for. If a match is found, the next step is taken.
tr = soup.find_all("tr")
name_url = "" #Enter the URL of the song you are looking for
flag = False
for tag_tr in tr:
a = tag_tr.find_all("a")
#It is stored in the order of song name, singer name, lyrics, and composition.
for i, tag_a in enumerate(a):
if i == 0: #Song title
name_url = tag_a.get("href")
elif i == 1: #Singer name
if tag_a.string == artist:
flag = True
break
if flag:
break
This time, it is necessary not only to open the lyrics page automatically, but also to close the previous page when switching to the next song. To do this, we use selenium, which can automate operations on the browser. For selenium, "Selenium in Python" is easy to understand.
First, let's access the URL we got earlier. As a whole, the loop is as follows.
First, open the browser before the loop.
#Open chrome
driver = webdriver.Chrome(executable_path="chromedriver")
#Initial tab of loop origin
driver.get("https://www.google.com/")
Then do 2 ~ 3 in the loop. At that time, the margin at the top of the lyrics page is an obstacle, so scroll the page.
#Open a new tab and move
driver.execute_script("window.open()")
driver.switch_to.window(driver.window_handles[1])
#Access the specified URL at the destination
driver.get("https://www.uta-net.com/" + name_url)
#Scroll to the position of the lyrics
driver.execute_script("window.scrollTo(0, 380);")
You can now view the lyrics of the song you are currently playing. All you have to do is loop this. Below is the entire code.
import appscript
from urllib import request, parse
from bs4 import BeautifulSoup
from selenium import webdriver
import time
driver = webdriver.Chrome(executable_path="chromedriver")
driver.get("https://www.google.com/") #Initial tab
music_time = 0
while True:
start = time.time()
# ----Get song title----
#Access the Music app
music = appscript.app("Music")
#Song name, album name, artist name, song length being played
name = music.current_track.name.get()
artist = music.current_track.artist.get()
album = music.current_track.album.get()
music_time = music.current_track.time.get() # m:s str
print(name, artist, album, music_time)
# music_Convert time to seconds
music_time = music_time.split(":")
music_time = int(music_time[0]) * 60 + int(music_time[1])
# ----Access the lyrics site----
name = parse.quote(name) #Percent encoding
url = "https://www.uta-net.com/search/?Aselect=2&Keyword=" + name + "&Bselect=4&x=0&y=0"
try:
html = request.urlopen(url)
soup = BeautifulSoup(html, "html.parser")
tr = soup.find_all("tr")
name_url = ""
flag = False
for tag_tr in tr:
a = tag_tr.find_all("a")
for i, tag_a in enumerate(a):
if i == 0: #Song title
name_url = tag_a.get("href")
elif i == 1: #Singer name
if tag_a.string == artist:
flag = True
break
if flag:
break
#Open in new tab
driver.execute_script("window.open()")
driver.switch_to.window(driver.window_handles[1])
driver.get("https://www.uta-net.com/" + name_url)
driver.execute_script("window.scrollTo(0, 380);") #Scroll to the position of the lyrics
#Close previous tab
driver.switch_to.window(driver.window_handles[0])
driver.close()
driver.switch_to.window(driver.window_handles[0])
except:
pass
print("now browsing")
print()
#Wait for the song time
time.sleep(music_time - (time.time() - start))
While writing this article, he keeps displaying the lyrics page safely. However, there were some inadequacies.
--It cannot be handled if there are symbols or spaces in the song title. -In the first place, you can not use it unless it is listed on the lyrics site --Every time you open the page, the window displaying the lyrics becomes active, so the work stops for a moment (about 2 seconds).
The above two are ignored by try-except (because it doesn't matter if you can't display them occasionally). Regarding the end, there is no choice but to display the lyrics.
Recommended Posts