zoukankan      html  css  js  c++  java
  • 抓取网易云音乐的评论

     

    原文 https://blog.csdn.net/xiaolei565/article/details/79693694

    一直喜欢使用网易云音乐,网易云歌曲下面的评论给其加分不少,所以这一篇来写一下怎么抓取歌曲下面的评论。
    准备工作

    • 目标网页:http://music.163.com/#/song?id=520458203(歌曲《大学无疆》)
    • API地址:http://music.163.com/api/v1/resource/comments/R_SO_4_520458203
    • 开发工具:pycharm
    • Python版本:3.6.4
    • 所需库:请求库requests,解析库json

    爬取过程分析
    第一步:根据API获取信息
    第二步:解析JSON数据
    第三步:使用多进程池获取每一页数据

    第一步:抓取页面并分析
    我们直接用谷歌浏览器打开目标网页,我们所需要的数据如下所示
    这里写图片描述
    按F12打开开发者工具,查看网页中评论的加载情况,找了一圈发现,网易云并没有很简单的直接在网页中显示评论,而是使用AjAx的异步加载方式,点击NetWork,勾选Preview log,选择XHR,我们可以看到如下图所示,我们点击R_SO_4_520458203?csrf_token=这一个Name可以很容易看到评论数据就是在这个请求中加载出来的。
    这里写图片描述
    从上图中可以明显看出请求地址是
    http://music.163.com/weapi/v1/resource/comments/R_SO_4_520458203?csrf_token=
    数据传递方式是POST
    然后我们选择Header,直接拖到下面看FormData,如下图所示这里写图片描述
    这也就是说明,POST方式传输了params和ensSecKey两个参数,明显有加密在里面,这也说明了网易云音乐对反扒做了一定的处理,因为对加密这一部分学习不深,我进行到这感觉进行不下去了,于是去知乎搜到了一个比较好理解的解密方法,传送门:https://www.zhihu.com/question/36081767(选择热门回答中的平胸小仙女和洛克的回答),我一想,这TM做个爬虫这么难啊,还要解谜,算了,不做了,结果发现天无绝人之路,我找到了一个不用解密的评论请求地址,在此感谢知乎:肖飞,传送门:如何爬网易云音乐的评论数? - 肖飞的回答 - 知乎
    不加密请求地址:
    http://music.163.com/api/v1/resource/comments/R_SO_4_520458203
    后面的数字为需要爬取的音乐的ID。下一篇我们介绍直接解密的方法抓取

    第二步:抓取页面并解析
    首先导入对应的库

    import requests
    from requests.exceptions import RequestException
    from urllib.parse import urlencode
    import json
    from multiprocessing import Pool#多进程池
     

     

     

    再定义第一个函数get_response(),用来抓取页面

    def get_response(offset,limit):
        #参数
        para = {
            'offset':offset,#页数
            'limit':limit#总数限制
        }
        # 歌曲id
        musicid = "520458203"  # 《大学无疆》
        #歌曲api地址
        musicurl = "http://music.163.com/api/v1/resource/comments/R_SO_4_"+musicid+"?"+urlencode(para)
        #头结构
        headers = {
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Accept-Encoding':'gzip, deflate, sdch',
            'Accept-Language':'zh-CN,zh;q=0.8',
            'Cache-Control':'max-age=0',
            'Connection':'keep-alive',
            'Cookie':'vjuids=-13ac1c39b.1620457fd8f.0.074295280a4d9; vjlast=1520491298.1520491298.30; _ntes_nnid=3b6a8927fa622b80507863f45a3ace05,1520491298273; _ntes_nuid=3b6a8927fa622b80507863f45a3ace05; vinfo_n_f_l_n3=054cb7c136982ebc.1.0.1520491298299.0.1520491319539; __utma=94650624.1983697143.1521098920.1521794858.1522041716.3; __utmz=94650624.1521794858.2.2.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; JSESSIONID-WYYY=FYtmJTTpVwmbihVrUad6u76CKxuzXZnfYyPZfK9bi%5CarU936rIdoIiVU50pfQ6JwjGgBvSyZO0%2FR%2BcoboKdPuMztgHCJwzyIgx1ON4v%2BJ2mOvARluNGpRo6lmhA%5CfcfCd3EwdS88sPgxpiiXN%5C6HZZEMQdNRSaHJlcN%5CXY657Faklqdh%3A1522053962445; _iuqxldmzr_=32',
            'Host':'music.163.com',
            'Upgrade-Insecure-Requests':'1',
            'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0'
        }
        #代理IP
        proxies= {
            'http:':'http://121.232.146.184',
            'https:':'https://144.255.48.197'
        }
        try:
    	    #用post方式接收数据
            response = requests.post(musicurl,headers=headers,proxies=proxies)
            if response.status_code == 200:
                return response.content
        except RequestException:
            print("访问出错")
     

     

     

    然后定义一个解析函数parse_return(),由于这个链接返回的是json数据,所以这个解析比较简单

    def parse_return(html):
        data = json.loads(html)#将返回的值格式化为json
        if data.get('hotComments'):
            hotcomm = data['hotComments']
            print('--------------------------------------------------------------这是热门评论-------------------------------------------------------------------------------')
            for hotitem in hotcomm:
                hotdata = {
                    '用户名': hotitem['user']['nickname'],
                    '用户头像': hotitem['user']['avatarUrl'],
                    'content': hotitem['content'],
                    '赞':hotitem['likedCount']
                }
                print(hotdata)
            print('------------------------------------------------------------------------------------------------------------------------------------------------------------')
        # else:
        #     print('--------------------------------------------------')
        if data.get('comments'):
            comm = data['comments']
            for item in comm:
                data = {
                    '用户名': item['user']['nickname'],
                    '用户头像': item['user']['avatarUrl'],
                    'content': item['content'].replace('
    ', ' '),
                    '赞': item['likedCount']
                }
                print(data)
            print('-------------------------------------------------------------------------------------------------------------------------------------------------------------')
     

     

    然后创建main函数

    def main(offset):
        gethtml = get_response(offset,200)
        parse_return(gethtml)
     

     

     

    使用多进程方法抓取全部页面

    if __name__ == '__main__':
    	#多进程池
        groups = [x*20 for x in range(0,20)]
        pool = Pool()
        pool.map(main,groups)
        #普通循环方法
        # for x in range(0,20):
        #    main(x*20)
     

     

     

    抓取结果如下
    这里写图片描述

    下面贴出全部代码,可以直接运行,只做学习使用

    # -*- coding: utf-8 -*-
    # @Time    : 2018/3/15 15:27
    # @Author  : XueLei
    # @Site    : 
    # @File    : neteasemusic.py
    # @Software: PyCharm
    #抓取某一首歌下面的评论
    
    import requests
    from requests.exceptions import RequestException
    from urllib.parse import urlencode
    import json
    from multiprocessing import Pool#多进程池
    
    def get_response(offset,limit):
        #参数
        para = {
            'offset':offset,#页数
            'limit':limit#总数限制
        }
        # 歌曲id
        musicid = "520458203"  # 《大学无疆》
        #歌曲api地址
        musicurl = "http://music.163.com/api/v1/resource/comments/R_SO_4_"+musicid+"?"+urlencode(para)
        #头结构
        headers = {
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Accept-Encoding':'gzip, deflate, sdch',
            'Accept-Language':'zh-CN,zh;q=0.8',
            'Cache-Control':'max-age=0',
            'Connection':'keep-alive',
            'Cookie':'vjuids=-13ac1c39b.1620457fd8f.0.074295280a4d9; vjlast=1520491298.1520491298.30; _ntes_nnid=3b6a8927fa622b80507863f45a3ace05,1520491298273; _ntes_nuid=3b6a8927fa622b80507863f45a3ace05; vinfo_n_f_l_n3=054cb7c136982ebc.1.0.1520491298299.0.1520491319539; __utma=94650624.1983697143.1521098920.1521794858.1522041716.3; __utmz=94650624.1521794858.2.2.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; JSESSIONID-WYYY=FYtmJTTpVwmbihVrUad6u76CKxuzXZnfYyPZfK9bi%5CarU936rIdoIiVU50pfQ6JwjGgBvSyZO0%2FR%2BcoboKdPuMztgHCJwzyIgx1ON4v%2BJ2mOvARluNGpRo6lmhA%5CfcfCd3EwdS88sPgxpiiXN%5C6HZZEMQdNRSaHJlcN%5CXY657Faklqdh%3A1522053962445; _iuqxldmzr_=32',
            'Host':'music.163.com',
            'Upgrade-Insecure-Requests':'1',
            'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0'
        }
        #代理IP
        proxies= {
            'http:':'http://121.232.146.184',
            'https:':'https://144.255.48.197'
        }
        try:
            response = requests.post(musicurl,headers=headers,proxies=proxies)
            if response.status_code == 200:
                return response.content
        except RequestException:
            print("访问出错")
    
    #解析返回页
    def parse_return(html):
        data = json.loads(html)#将返回的值格式化为json
        if data.get('hotComments'):
            hotcomm = data['hotComments']
            print('--------------------------------------------------------------这是热门评论-------------------------------------------------------------------------------')
            for hotitem in hotcomm:
                hotdata = {
                    '用户名': hotitem['user']['nickname'],
                    '用户头像': hotitem['user']['avatarUrl'],
                    'content': hotitem['content'],
                    '赞':hotitem['likedCount']
                }
                print(hotdata)
            print('------------------------------------------------------------------------------------------------------------------------------------------------------------')
        # else:
        #     print('--------------------------------------------------')
        if data.get('comments'):
            comm = data['comments']
            for item in comm:
                data = {
                    '用户名': item['user']['nickname'],
                    '用户头像': item['user']['avatarUrl'],
                    'content': item['content'].replace('
    ', ' '),
                    '赞': item['likedCount']
                }
                print(data)
            print('-------------------------------------------------------------------------------------------------------------------------------------------------------------')
    def main(offset):
        gethtml = get_response(offset,200)
        parse_return(gethtml)
    
    if __name__ == '__main__':
        # groups = [x*20 for x in range(0,20)]
        # pool = Pool()
        # pool.map(main,groups)
        for x in range(0,20):
            main(x*20)
     

     

     

    第二篇一直没写,因为暂时不在做这方面了,辞职读书去了,所以暂时搁置,有时间再来补上

  • 相关阅读:
    django-day3 Ajax
    django ORM 一对多, 多对多 查询 以及 结合Tamplate
    work-python 脚本 每日发送数据查询
    day16- django
    day15 Jquery
    day 14 JS 练习
    day14 JS-DOM 对象
    day14 JS-BOM
    day14 JS 对象 Function
    day14 js
  • 原文地址:https://www.cnblogs.com/brady-wang/p/11859381.html
Copyright © 2011-2022 走看看