靓汤有时还不怎么样

2024-06-06 04:30:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试图为一个学校项目构建一个刮板,以刮板天才的歌词,我发现了以下代码:

def scrape_song_lyrics(url):
    page = requests.get(url)
    html = BeautifulSoup(page.text, 'html.parser')
    lyrics = html.find('div', class_='lyrics').get_text()
    #remove identifiers like chorus, verse, etc
    lyrics = re.sub(r'[\(\[].*?[\)\]]', '', lyrics)
    #remove empty lines
    lyrics = os.linesep.join([s for s in lyrics.splitlines() if s])         
    return lyrics

我在GoogleColab中运行它,但是,我遇到了一些问题,它有时工作,有时不工作,错误是'NoneType' has no attribute 'get_text',我认为这是因为HTML没有正确加载。 我知道在这个话题上有很多问题,有很多答案,包括使用urllib.requestselenium,但是没有一个对我有用

我特别好奇的是,为什么有时有效,有时无效。我已经重新开始运行了几次,有时一切都像一个符咒一样工作,有时它根本不起作用,我在两个场景之间没有对代码进行任何更改。 我需要刮很多歌曲(大约10000首),所以我真的需要这个刮片工作可靠,提前谢谢


Tags: 项目代码text刮板urlgetdefhtml
2条回答

在第3行中,lyrics = lyrics = html.find('div', class_='lyrics').get_text()您可以看到它首先调用了html.find('div', class='lyrics'),然后在该行上调用了.get_text()方法。目标站点中可能存在HTML解析器找不到div的页面,在这种情况下返回None。解析器找不到目标div可能有多种原因。可能是因为div不存在,也可能是因为解析器在隐式时间限制内找不到目标div

当您试图在None上调用.get_text()时,python正在提升AttributeError

您必须始终在web抓取代码中处理这些类型的错误。您可以做的是处理错误并忽略它,因为它是预期的。您可以这样做:

def scrape_song_lyrics(url):
    page = requests.get(url)
    html = BeautifulSoup(page.text, 'html.parser')
    
    try:
        lyrics = html.find('div', class_='lyrics').get_text()
    except AttributeError:
        print('cannot find the target div: lyrics')
        return None
    
    else:
        #remove identifiers like chorus, verse, etc
        lyrics = re.sub(r'[\(\[].*?[\)\]]', '', lyrics)
        #remove empty lines
        lyrics = os.linesep.join([s for s in lyrics.splitlines() if s]) 
        return lyrics

当错误发生时,它将返回None,而不是抛出属性错误。然后,如果需要,可以编写一个重试逻辑,调用方将在被调用方返回None时重试运行被调用方

问题是,服务器返回两个版本的HTML页面。要从两个版本中获取歌词,可以使用以下示例:

import os
import re
import requests
from bs4 import BeautifulSoup
  

def scrape_song_lyrics(url):
    page = requests.get(url)
    html = BeautifulSoup(page.text, "html.parser")
    lyrics = html.select_one(
        'div[class^="lyrics"], div[class^="SongPage__Section"]'
    ).get_text(separator="\n")
    # remove identifiers like chorus, verse, etc
    lyrics = re.sub(r"[\(\[].*?[\)\]]", "", lyrics)
    # remove empty lines
    lyrics = os.linesep.join([s for s in lyrics.splitlines() if s])
    return lyrics

对于测试,您可以使用例如:

url = "https://genius.com/Billie-eilish-your-power-lyrics"

for i in range(100):
    print(scrape_song_lyrics(url))
    print(i, "-" * 100)

相关问题 更多 >