使用Requests/BS4爬取MetroLyrics歌词时Unicode字符显示异常
解决MetroLyrics歌词爬取的Unicode乱码问题
看起来你的问题出在字符编码处理不当和歌词提取方式不够严谨这两个地方,我来帮你一步步解决:
问题根源分析
你看到的Kashèr、ḤalÄl这类乱码,本质是UTF-8编码的文本被当成了Latin-1(ISO-8859-1)解码导致的。requests默认会根据响应头的Content-Type猜测编码,但有时候网站返回的编码标识不准确,就会出现这种情况。另外,你直接把BeautifulSoup的Tag对象转成字符串再手动替换HTML实体的方式,不仅繁琐,还容易引入编码问题。
修复后的完整代码
import requests from bs4 import BeautifulSoup try: from urllib.parse import quote_plus except ImportError: from urllib import quote_plus def get_lyrics(song_name): song_name += ' metrolyrics' name = quote_plus(song_name) hdr = { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11', 'Accept-Language': 'en-US,en;q=0.8', 'Connection': 'keep-alive' } # 处理搜索请求,强制使用自动检测的真实编码 url = 'http://www.google.com/search?q=' + name search_response = requests.get(url, headers=hdr) search_response.encoding = search_response.apparent_encoding result = search_response.text link_start = result.find('http://www.metrolyrics.com') if link_start == -1: return "Lyrics not found on Metrolyrics" link_end = result.find('html', link_start + 1) link = result[link_start:link_end + 4] # 处理歌词页面,同样设置正确编码 lyrics_response = requests.get(link, headers={ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36' }) lyrics_response.encoding = lyrics_response.apparent_encoding soup = BeautifulSoup(lyrics_response.text, "lxml") # 优化歌词提取:直接获取标签文本,自动处理HTML实体和格式 raw_lyrics = soup.find_all('p', attrs={'class': 'verse'}) final_lyrics = '\n\n'.join([verse.get_text(strip=False, separator=' ') for verse in raw_lyrics]) return final_lyrics
关键改动说明
- 编码强制修正:给每个requests响应设置
response.encoding = response.apparent_encoding,这个方法会根据响应内容自动检测真实编码,比依赖网站返回的Content-Type更可靠,从根源解决乱码问题。 - 歌词提取优化:使用
verse.get_text(strip=False, separator=' ')直接获取每个verse标签内的纯文本,BeautifulSoup会自动处理<br/>这类HTML实体和换行,不需要手动替换字符串,既简洁又避免了编码错误。 - 排版优化:用
'\n\n'分隔不同的verse,让歌词排版更接近原网页的格式。
为什么原有方法无效?
你尝试的.encode('utf-8')之类的操作,属于“亡羊补牢”——文本已经被错误解码成乱码了,再编码也无法恢复原来的正确字符。必须在获取响应后立刻设置正确的编码,才能保证后续处理的文本是正确的。另外,直接把Tag对象转成字符串会包含原始的HTML标签和未解析的实体,手动替换不仅容易遗漏,还可能在替换过程中引入编码二次错误。
内容的提问来源于stack exchange,提问作者nautilor
相关产品推荐
相关产品推荐

