Web Scraping: пытается восстановить все песни, но возвращается только один текст - PullRequest
1 голос
/ 21 января 2020

Я хочу удалить текст всей песни, но проблема в том, что она дает лири c только одной песни.

Фрагмент кода:

import requests
from bs4 import BeautifulSoup
import pandas

url = "https://www.lyrics.com/album/3769520/Now+20th+Anniversary%2C+Vol.+2"
req = requests.get(url)
html = req.content
soup = BeautifulSoup(html , 'html.parser')

tags = soup.find_all('strong')
name = ""
Length = len(tags)
Length = Length - 3 # because it gives extra things
newUrl = "https://www.lyrics.com/lyric/35873930/"
for index in range(1 , Length):
    SongName = tags[index].text.replace(" ","")
    FileName = tags[index].text + ".txt"
    newFetechedUrl = newUrl + SongName
#    print(newFetechedUrl)
    req1 = requests.get(newFetechedUrl)
    html1 = req1.content
    soup1 = BeautifulSoup(html1, 'html.parser')
    Lyrics = soup1.find_all("pre", {"id": "lyric-body-text"})
    print(Lyrics[0].text)
    req2 = requests.get(url)
    html2 = req2.content
    soup2 = BeautifulSoup(html2, 'html.parser')
    tags = soup2.find_all('strong')
#    print(tags[index].text.replace(" ",""))
    File = open(FileName,"w")
    File.close()

Я хочу, чтобы все песни были на этой странице я не знаю, почему она дает только первую песню

Ответы [ 2 ]

3 голосов
/ 21 января 2020

Использование BeautifulSoup (или, точнее, использование модуля requests для проверки связи с веб-сайтом) линейным способом, особенно при многократном использовании, может быть медленным и неэффективным. Я немного изменил ваш код, добавил многопоточность для ускорения выполнения и упростил чтение.

import requests
import concurrent.futures
from bs4 import BeautifulSoup

# Parse the initial 'album' website 
req = requests.get(url)
html = req.content
soup = BeautifulSoup(html , 'html.parser')

# Find all song's links in 'album' site - these can be found under
# the 'strong' tab, and 'a' tab
links = [tag.a["href"] for tag in soup.find_all('strong')[1:-3]] 

def getLyrics(url):
    url = HOST + url # songs are found on the HOST website
    # Parse 'song' site
    req = requests.get(url)
    html = req.content
    soup = BeautifulSoup(html , 'html.parser')
    # Obtain the lyrics, which can be found under the 'pre' tab
    return soup.find('pre').text

# Use multi-threading for faster performance - I'll give a small run down:
# max_workers = number of threads - we use an individual thread for each song
with concurrent.futures.ThreadPoolExecutor(max_workers=len(links)) as executor:
    # for every song...
    for j in range(len(links)):
        # run the 'getLyrics' method on an individual thread and get the lyrics
        lyrics = executor.submit(getLyrics, links[j]).result()
        # do whatever with the lyrics ... I simply printed them
        print(lyrics)

Модуль concurrent.futures предоставляет хороший интерфейс для многопоточности. Подробнее об этом можно прочитать в его документации - здесь

Конечно, вы можете еще больше измените его, сделайте его еще более эффективным и измените его в соответствии с вашими потребностями - но это должно быть базовым c решением вашего вопроса.

1 голос
/ 21 января 2020

Этот код извлечет все названия песен и тексты песен с каждой страницы и сохранит их в словаре с заголовком песни:

import requests
from bs4 import BeautifulSoup
import pandas

BASE_URL = "https://www.lyrics.com"

def get_song_and_lyrics(path):
    new_url = BASE_URL + path
    r = requests.get(new_url)
    soup = BeautifulSoup(r.content , 'html.parser')
    return soup.find('h1').text, soup.find('pre').text


url = BASE_URL + "/album/3769520/Now+20th+Anniversary%2C+Vol.+2"

r = requests.get(url)
soup = BeautifulSoup(r.content , 'html.parser')
tags = soup.find_all('strong')

song_links = []
# iterate over each song entry and grab the link to the lyrics
for s in tags:
    link = s.find('a')
    if link and link['href'].startswith('/lyric'):
        song_links.append(link['href'])

songs = {}
# then we iterate over all the lyric links and get the lyrics for each song
# those lyrics are then stored in songs[song_title]
for l in song_links:
    song,lyrics = get_song_and_lyrics(l)
    songs[song] = lyrics

, например:

print songs['Toxic']

будет напечатано текст Toxi c

В нашей функции get_song_and_lyrics мы передаем относительный путь к тексту песни и создаем новый суповой объект с содержимым этой страницы. Название песни сохраняется в первом элементе <h1>, а текст песни - в первом элементе <pre>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...