Let's automatically display the lyrics of the song being played on iTunes in Python

Introduction

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)"

Thing you want to do

Play a song with the standard Mac app "Music" and automatically display the lyrics on the lyrics site each time the song changes.

environment

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.

Get song title

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])

Display lyrics

Find the lyrics page

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

Display lyrics page

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.

  1. The song changes ↓
  2. Open a new tab to access the lyrics page ↓
  3. Close the previous tab ↓ 4.1 Return to 1

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);")

Complete

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))

in conclusion

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

Let's automatically display the lyrics of the song being played on iTunes in Python
Let's automatically display the lyrics of the song being played on iTunes in Python (improved version)
Not being aware of the contents of the data in python
Let's use the open data of "Mamebus" in Python
Waveform display of audio in Python
How is the progress? Let's get on with the boom ?? in Python
Let's measure the test coverage of pushed python code on GitHub.
[Cloudian # 9] Try to display the metadata of the object in Python (boto3)
Get the number of readers of a treatise on Mendeley in Python
Check the behavior of destructor in Python
Django ~ Let's display it in the browser ~
Display a list of alphabets in Python 3
Display Python 3 in the browser with MAMP
Let's change the color scheme of iTerm2 automatically depending on the time zone
The result of installing python in Anaconda
Let's claim the possibility of pyenv-virtualenv in 2021
Display the graph of tensorBoard on jupyter
[Android] Display images on the web in the info Window of Google Map
The basics of running NoxPlayer in Python
In search of the fastest FizzBuzz in Python
I tried to get the RSS of the top song of the iTunes store automatically
I want to use Python in the environment of pyenv + pipenv on Windows 10
I installed Pygame with Python 3.5.1 in the environment of pyenv on OS X
Let's play with Python Receive and save / display the text of the input form
In Python, change the behavior of the method depending on how it is called
Set an upper limit on the number of recursive function iterations in Python
Visualize the timeline of the number of issues on GitHub assigned to you in Python
Output the number of CPU cores in Python
[Python] Sort the list of pathlib.Path in natural sort
Let's parse the git commit log in Python!
Get the caller of a function in Python
Match the distribution of each group in Python
View the result of geometry processing in Python
Make a copy of the list in Python
Find the divisor of the value entered in python
[Python] Display the Altair legend in the plot area
Find the solution of the nth-order equation in python
The story of reading HSPICE data in Python
[Note] About the role of underscore "_" in Python
About the behavior of Model.get_or_create () of peewee in Python
Solving the equation of motion in Python (odeint)
Output in the form of a python array
At the time of python update on ubuntu
I want to display the progress in Python!
[Example of Python improvement] I learned the basics of Python on a free site in 2 weeks.
[Machine learning] "Abnormality detection and change detection" Let's draw the figure of Chapter 1 in Python.
Let's get notified of the weather in your favorite area from yahoo weather on LINE!
Display n digits after the decimal point in python
Experience the good calculation efficiency of vectorization in Python
Sort in Python. Next, let's think about the algorithm.
[python] Get the list of classes defined in the module
Let's break down the basics of TensorFlow Python code
The story of FileNotFound in Python open () mode ='w'
Learn the design pattern "Chain of Responsibility" in Python
Implement the solution of Riccati algebraic equations in Python
Get the size (number of elements) of UnionFind in Python
Let's use the Python version of the Confluence API module.
Difference in results depending on the argument of multiprocess.Process
Reproduce the execution example of Chapter 4 of Hajipata in Python
Write a log-scale histogram on the x-axis in python
Implemented the algorithm of "Algorithm Picture Book" in Python3 (Heapsort)