Получение текстов песен из Musixmatch - PullRequest
0 голосов
/ 18 июня 2020
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()



Я пытаюсь получить ВСЕ тексты песен исполнителя и сохранить их в базе данных. Например, если исполнителем является «Drake», я хочу, чтобы все тексты песен хранились в ключе «lyrics» в моей базе данных.

Однако я получаю кучу непредсказуемых ошибок каждый раз, когда запускаю один и тот же код. Например, без проблем вставлял бы 400 слов песен, и внезапно я получаю сообщение об ошибке, что «индексы списка должны быть целыми числами или фрагментами, а не str». Эта ошибка меня довольно сбивает с толку, потому что я предполагаю, что все данные json находятся в одном формате, и у меня возникла внезапная ошибка после обработки 400 текстов песен без проблем введите описание изображения здесь

Я могу запустить тот же код, и примерно при 200 текстах песен я получу ошибку декодирования json, а затем, когда я смогу запустить его СНОВА, и после обработки другого количества текстов песен я получу ошибка, которую я описал в начале снова.

Может кто-нибудь объяснить случайный характер этой ошибки?

Спасибо!

1 Ответ

0 голосов
/ 18 июня 2020

Вы делаете предположения о типах данных, которые будут возвращены из JSON. В вашем случае я подозреваю, что один из элементов json является списком, а не объектом.

Ваша проблема может быть воспроизведена с помощью этого простого примера:

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

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

дает:

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

Как исправить? Вам нужно будет проверить соответствие каждого элемента тому, что вы ожидаете; например:

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

дает:

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