https://y.qq.com/portal/search.html#page=1&searchid=1&remoteplace=txt.yqq.top&t=lyric&w=%E5%91%A8%E6%9D%B0%E4%BC%A6
爬取歌词这道题,有的同学找歌词的时候,会直接点进一首歌的详情页,然后打开“检查”,先在element去找,然后按照<div class='lyric_cont_box'>去定位
结果发现是爬取不到内容的
那爬不到的时候,我们就要去看看Network里面的内容
检查一下,ALL的第一个请求,是否网页的第0个请求里面是否有我们要抓取的内容?
操作如下,选择Network,选择ALL,刷新一下页面,选择第一个请求,名称是“004Fs2FP1EvZYc.html”
看看Preveiw的内容,好像没有我们想要的歌词内容也
那咋办?走!到XHR找找去
寻寻觅觅之后,发现了有这么一个请求,名称是:fcg_query_lyric_yqq.fcg......反正有个lyric(歌词的意思)
点开看看Preview的内容,果然有歌词
接下来,爬它!
既然是在XHR里面的内容,那爬取的方法就是:
用requests.get()去请求数据,请求数据后,需要用json()进行解析,解析完成后再按字典和列表的格式去提取数据
自动检测
import re,requests
lyric_url = 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_yqq.fcg'
headers = {
'origin': 'https://y.qq.com',
'referer': 'https://y.qq.com/n/yqq/song/004Fs2FP1EvZYc.html',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
}
params = {
'nobase64': '1',
'musicid': '244115385',
'-': 'jsonp1',
'g_tk': '',
'loginUin': '0',
'hostUin': '0',
'format': 'json',
'inCharset': 'utf8',
'outCharset': 'utf-8',
'notice': '0',
'platform': 'yqq.json',
'needNewCode': '0'
}
res_lyric = requests.get(lyric_url,headers=headers,params=params)
json_lyric = res_lyric.json()
lyric = json_lyric['lyric']
print(lyric)
打印出来的结果如下:
爬是爬下来了,这也太乱七八糟了吧。助教有一种方法,把数据处理一下
在上面代码的最末尾,加上这么一段即可:
自动检测
for i in lyric.split('
'):
music_str = re.sub('[A-Za-z0-9\\!\\%\\[\\]\\,\\。\\&\\#\\;]', '', i)#用正则表达式去掉无用的符号字符
if music_str.strip():#strip去掉空行
print(music_str)
简单地说一下这里用到的是“正则表达式”的知识,因为课堂里没有这个知识点的讲解,所以助教这里不做拓展哈~
到这里,我们确实爬取到了歌词的内容,但是,这样却只能爬取到一首歌的歌词啊。好像不符合题目要求也,那...我们是不是找错了?
嗯,也不是错,但是不太符合题目的要求
其实,题目原本希望我们去抓取的,是下面这个页面
在歌手的搜索页里,我们可以切换到“歌词”这一块的内容
同样我们先在ALL里面查看第0个请求
然后我们发现,数据依然不在这里。在这个html里面,是没有我们需要抓取的歌词内容信息的
也就是说,我们没有办法通过element去爬取歌词
下一步应该怎么做?
....(思考一下)
或许你已经想到了,我们就得从XHR里面去找了
如果没找到,那我们刷新一下页面,再用助教之前讲过的小技巧,给请求按Size排序来快速找到我们需要的请求。果然,client_search_cp 这个请求是最大的,排在最前面
既然是在XHR里面的内容,那再回忆一下爬取的方法:
1、requests.get()去请求数据,记得带上参数Params和Headers
2、请求数据后,需要用json()进行解析
3、解析完成后再按字典和列表的格式去提取数据
自动检测
import requests
import json
# 引用requests,json模块
url = 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp'
headers = {
'referer':'https://y.qq.com/portal/search.html',
# 请求来源
'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
# 标记了请求从什么设备,什么浏览器上发出
}
for x in range(5):
params = {
'ct':'24',
'qqmusic_ver': '1298',
'new_json':'1',
'remoteplace':'sizer.yqq.lyric_next',
'searchid':'94267071827046963',
'aggr':'1',
'cr':'1',
'catZhida':'1',
'lossless':'0',
'sem':'1',
't':'7',
'p':str(x+1),
'n':'10',
'w':'周杰伦',
'g_tk':'1714057807',
'loginUin':'0',
'hostUin':'0',
'format':'json',
'inCharset':'utf8',
'outCharset':'utf-8',
'notice':'0',
'platform':'yqq.json',
'needNewCode':'0'
}
res = requests.get(url, params = params)
#下载该网页,赋值给res
jsonres = res.json()
#使用json来解析res.text
list_lyric = jsonres['data']['lyric']['list']
#一层一层地取字典,获取歌词的列表
for lyric in list_lyric:
#lyric是一个列表,x是它里面的元素
print(lyric['content'])
#以content为键,查找歌词
果然,这样我们可以实现5个页面所有歌词的爬取了!
这个过程,也就是我们经过一番研究之后发现,从最初搜索结果的页面去爬取歌词是最方便简洁的
再补充一下,爬取歌词这个练习,第一次爬取下来的歌词呈现的效果如下
爬是爬下来了,怎么又太乱七八糟了吧。助教还有一种方法,把数据处理一下
解决方法:歌词里面\n其实是\\n来的,用字符串.replace('\\n','\n')就可以换行了,这是因为爬出来的歌词里面的\\n,然后打印的时候遇到\\n,会打印成\n
参考一下代码:
自动检测
for lyric in list_lyric:
print(lyric['content'].replace('\\n','\n'))
隐藏的终极版本:(电脑打开下载可看)
5关_歌词单曲页爬取.py2.9KB