简体   繁体   English

从 Musixmatch 中检索歌词

[英]Retrieving Lyrics from Musixmatch

import requests
import json
import urllib
import lyricsgenius
import os
import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.keys import Keys


from bs4 import BeautifulSoup


from pymongo import MongoClient

client = MongoClient('localhost', 27017)
db = client.dbsparta

def get_artist_id(artistName):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
    response = requests.get("https://api.musixmatch.com/ws/1.1/artist.search?page_size=100&format=json&apikey=123&q_artist=" + artistName, headers=headers)
    response.encoding = 'UTF-8'
    return response.json()['message']['body']['artist_list'][0]['artist']['artist_id']
    # print(response.json()['message']['body']['artist_list'][0]['artist']['artist_id'])



def get_album_ids(artist_id):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
    album_response = requests.get("https://api.musixmatch.com/ws/1.1/artist.albums.get?page_size=100&format=json&apikey=123&artist_id=" + str(artist_id), headers=headers)
    album_response.encoding = 'UTF-8'
    # counter = 0
    # album_list = album_response.json()['message']['body']['album_list']
    return album_response.json()['message']['body']['album_list']
    # print(album_response.json()['message']['body']['album_list'])


    # for album in album_list:
    #     # counter += 1
    #     print(album['album']['album_id'])

def get_album_tracks_ids(album_id):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
    response = requests.get("https://api.musixmatch.com/ws/1.1/album.tracks.get?page_size=100&format=json&apikey=123&album_id=" + str(album_id), headers=headers)
    response.encoding = 'UTF-8'
    return response.json()['message']['body']['track_list']


# def get_track_id(artist_id):
#     headers = {
#         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
#     response = requests.get("https://api.musixmatch.com/ws/1.1/track.search?page_size=100format=json&apikey=123&f_artist_id=" + str(artist_id), headers=headers)
#     response.encoding = 'UTF-8'
#     for tracks in response.json()['message']['body']['track_list']:
#         print(tracks['track']['track_name'])

def get_track_lyrics(track_id):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
    response = requests.get("https://api.musixmatch.com/ws/1.1/track.lyrics.get?apikey=123&track_id=" + str(track_id), headers=headers)
    response.encoding = 'UTF-8'
    # return response['message']['body']['lyrics']['lyrics_body']
    return response.json()['message']['body']['lyrics']['lyrics_body']



def main():
    stars_list = list(db.new_top200.find({}, {'_id': 0}))
    for stars in stars_list:
        print(stars['name'])
        album_ids = get_album_ids(get_artist_id(stars['name']))
        # if album_ids is not None:
        for album_id in album_ids:
            # if album_id is not None and get_album_tracks_ids(album_id['album']['album_id']) is not [] and get_album_tracks_ids(album_id['album']['album_id']) is not None:
            track_ids = get_album_tracks_ids(album_id['album']['album_id'])
            for track in track_ids:
                # if track is not [] and track['track']['track_id'] is not [] and track is not None:
                #     if get_track_lyrics(track['track']['track_id']) is not [] and get_track_lyrics(track['track']['track_id']) is not None:
                lyric = get_track_lyrics(track['track']['track_id'])
                db.new_top200.update_one({'name': stars['name']},{'$push': {'lyrics': lyric } })


# get_track_id(get_artist_id('Kanye West'))

# get_album_ids(get_artist_id("Kanye West"))
# get_album_tracks(15565713)


if __name__ == "__main__":
    # for album in get_album_ids(get_artist_id("Kanye West")):
    #     get_album_tracks_ids(album['album']['album_id'])
    # get_track_lyrics(96610952)
    # get_album_tracks_ids(15565713)
    # get_album_ids(get_artist_id('Drake'))
    main()



I'm trying to get ALL of the lyrics of an artist and store it in a database.我正在尝试获取艺术家的所有歌词并将其存储在数据库中。 For example, if the artist is "Drake" I want all of the lyrics stored in the 'lyrics' key in my database.例如,如果艺术家是“Drake”,我希望所有歌词都存储在数据库中的“lyrics”键中。

However, I get a bunch of unpredictable errors every time I run the same code.但是,每次运行相同的代码时,都会遇到一堆不可预知的错误。 For example, it would be inserting 400 lyrics without any problem and suddenly I'll get an error saying that 'list indices must be integers or slices not str'.例如,它会毫无问题地插入 400 条歌词,突然我会收到一条错误消息,说“列表索引必须是整数或切片而不是 str”。 This error is quite confusing to me because I'm assuming that all of the json data are in the same format and I have a sudden error after processing 400 song lyrics with no problem enter image description here这个错误让我很困惑,因为我假设所有 json 数据都采用相同的格式,并且在处理 400 首歌词后突然出现错误,在此处输入图像描述

I can run the same code and at about 200 song lyrics in, I'll get a json decode error and then when I can run it AGAIN and after processing a different amount of song lyrics I'll get the error I described in the beginning again.我可以运行相同的代码,并且在大约 200 首歌词中,我会得到 json 解码错误,然后当我可以再次运行它并处理不同数量的歌词后,我会得到我在开始时描述的错误再次。

Can someone explain the random nature of this error?有人可以解释这个错误的随机性吗?

Thank you!谢谢!

You are making assumptions about the data types that will be returned from the JSON.您正在对将从 JSON 返回的数据类型进行假设。 In your case I suspect that one of the json elements is a list not an object.在您的情况下,我怀疑 json 元素之一是列表而不是 object。

Your issue can be reproduced with this simple example:您的问题可以通过这个简单的示例重现:

my_dict = {
    'message': {
        'body': {
            'lyrics': ['Always look on the bright side of life']
        }
    }
}

print(my_dict['message']['body']['lyrics']['lyrics_body'])

gives:给出:

TypeError: list indices must be integers or slices, not str

How do you fix it?你如何解决它? You'll need to check each element matches what you expect;您需要检查每个元素是否符合您的预期; for example:例如:

my_dict = {
    'message': {
        'body': {
            'lyrics': ['Always look on the bright side of life']
        }
    }
}

def checker(item, field):
    if isinstance(item, dict):
        return item.get(field)
    else:
        raise ValueError(f"'{item}' in field '{field}' is not a valid dict")


message = checker(my_dict, 'message')
body = checker(message, 'body')
lyrics = checker(body, 'lyrics')
print(checker(lyrics, 'lyrics'))

gives:给出:

ValueError: '['Always look on the bright side of life']' in field 'lyrics' is not a valid dict

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM