爬虫练习:爬取网易云音乐热歌榜全部歌曲的热门评论

目标:爬取网易云音乐热歌榜中全部歌曲(共200首)的热门评论(每首歌有15个热门评论)

分析:

需要分两步走,第一步是定位到热歌榜单所在的资源,从而得到这热歌榜中到底有哪些歌并获得每首歌的id;第二步是根据上一步得到的每首歌的id,定位到单独每首歌所在的资源,从而得到每首歌下的评论信息。具体讲:

1)首先我们需要得到热歌榜数据所在的url,经浏览器开发者工具查看网页代码,得知热歌榜的数据所在的请求url是:

http://music.163.com/discover/toplist?id=3778678

这个url的请求方式是get方式,返回的是html的doc文档,这个文档中的第610行就包含了每首歌的歌名,id,以及对应的播放资源链接。

所以我们的第一个任务就是把该html文档爬取下来,提取出所有歌曲的名称及id。有了歌曲id之后,我们可以进一步通过这个id访问到每一首歌的具体信息。

2)在网页上点进某一首歌的链接,分析弹出的每首歌单独的新页面的Network情况,我们可以分析出包含该首歌歌评的请求url为:

http://music.163.com/weapi/v1/resource/comments/R_SO_4_489998494?csrf_token=,

请求方式是post(因为评论需要往服务端发送数据),返回的是json文件,在该json文件中就包含了我们需要的热门评论。在这里唯一有点棘手的地方是发送post请求时需要两个参数,而不同的歌这两个参数是不同的(然而程序中用的参数是相同的),关于这两个参数如何定,具体介绍在下面的链接中。

所以下一步任务就是通过post请求把该json文件爬取下来,并提取出其中的热门评论信息。

下面代码的详细介绍请参见:https://blog.csdn.net/fengxinlinux/article/details/77950209

#获取网易云热歌榜所有歌曲的名称和id
def get_all_hotSong():
    url = "http://music.163.com/discover/toplist?id=3778678"                   #网易云音乐热歌榜url
    
    ua_headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) \
                                AppleWebKit/537.36 (KHTML, like Gecko) \
                                Chrome/60.0.3112.101 \
                                Safari/537.36'}                                #请求头部           
                            
    request = urllib.request.Request(url=url, headers=ua_headers)              #构造请求对象
    
    html = urllib.request.urlopen(request).read().decode('utf8')               #打开url
    
    html = str(html)                                                           #转换为str
    
    #我们要筛选的html字段例如:<ul class="f-hide"><li><a href="/song?id=574566207">说散就散</a></li></ul>
    
    part1 = r'<ul class="f-hide"><li><a href="/song\?id=\d*?">.*</a></li></ul>'#进行第一次筛选的正则表达式,注意在这里有问号(本身是正则表达式的元字符)前要使用转义符\
                                                                               
    result = re.compile(part1).findall(html)                                   #用正则表达式进行筛选,返回的结果存在列表中
    
    result = result[0]                                                         #获取list的第一个元素
    
    part2 = r'<li><a href="/song\?id=\d*?">(.*?)</a></li>'                     #进行歌名筛选的正则表达式
    
    part3 = r'<li><a href="/song\?id=(\d*?)">.*?</a></li>'                     #进行歌id筛选的正则表达式
    
    hot_song_name = re.compile(part2).findall(result)                          #获取所有热门歌曲名称
    
    hot_song_id = re.compile(part3).findall(result)                            #获取所有热门歌曲id
    
    return hot_song_name, hot_song_id                                          #返回的是两个list

#参数是歌曲名和id(由上一个函数返回),返回的是每首歌下的15条热评
def get_hotComments(hot_song_name, hot_song_id):
    #每首歌使用单独的url请求
    url = 'https://music.163.com/weapi/v1/resource/comments/R_SO_4_' + hot_song_id + '?csrf_token='               
    ua_headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) \
                                AppleWebKit/537.36 (KHTML, like Gecko) \
                                Chrome/60.0.3112.101 \
                                Safari/537.36'}                                #请求头部 
    #post请求表单数据,以字典形式组织参数                            
    data = {'params':'Ms46IEnUeE4P/yfU6xsyEtEcjeRfhckhg/sBdqIG2tLBXGPoZ7MGVOZsu2AdyLQ+ZTPDvjf1OjalqcSSJLfBmf1vvbVx8cvv8MVoHYOQ6wCRnd2/6+GMfu1M13fbNXVb9aKiduqxPZjZrMsTgX5jecxsXs/rzP9KLRWDDMkvxusGini/WGaWDKGrBQj4cm4k', \
            'encSecKey':'b049e6104264186dfaceba5f9a60dc39e8cf6900dac42a58223074346b758a4ca0fc66006a39a8d54e43cc95c271b415b69efa8a81742f06230a105e32a6f11128e8d526450a81f3245ce0fb5f5974de18207e6e3cdaf87b63572fcb7ad720124b19049457fe19c8f7f3424c3eae45d530b743ee7dec5ef78d15c2dbbc258975'}
    
    postdata = urllib.parse.urlencode(data).encode('utf8')                     #将参数进行编码
    
    request = urllib.request.Request(url, headers=ua_headers, data=postdata)   #构造请求对象
    
    response = urllib.request.urlopen(request).read().decode('utf8')           #打开url,返回类文件对象并读其内容
    
    json_dict = json.loads(response)                                           #获取json
    
    hot_comments = json_dict['hotComments']                                    #获取json中的热门评论
    
    num = 0
    fhandle = open('./song_comments.txt','a', encoding='utf-8')                #按appendix的方式打开文件
    fhandle.write(hot_song_name+':'+'\n')
    
    for item in hot_comments:                                                  #按循环依次写入歌的每条评论
        num += 1
        fhandle.write(str(num)+'.'+item['content']+'\n')
    fhandle.write('\n==============================\n\n')
    fhandle.close()
#==============================主程序入口=======================================
#返回网易云热歌榜所有歌曲的名称和id    
hot_song_name, hot_song_id = get_all_hotSong()                                 

num = 0
while num < len(hot_song_name):
    print('正在抓取第%d首歌曲热评...'%(num+1))
    get_hotComments(hot_song_name[num], hot_song_id[num])
    print('第%d首歌曲热评抓取成功'%(num+1))
    num += 1

猜你喜欢

转载自blog.csdn.net/qq_41230365/article/details/82155738