爬虫综合大作业

选择一个热点或者你感兴趣的主题。

选择爬取的对象与范围。

了解爬取对象的限制与约束。

爬取相应内容。

做数据分析与文本分析。

形成一篇文章,有说明、技术要点、有数据、有数据分析图形化展示与说明、文本分析图形化展示与说明。

文章公开发布。

1. 数据爬取

我们本次爬取的对象是一首名为《five hours》的经典电音流行歌曲,Five Hours是Erick Orrosquieta于2014年4月发行的单曲,当年这首单曲就出现在奥地利,比利时,法国,荷兰,挪威,瑞典和瑞士的榜单中。

作者Erick Orrosquieta,一般为人熟知的是他的艺名Deorro,2014年世界百大DJ排名十九位。1991年8月29日生于美国洛杉矶,墨西哥血统的音乐制作人,签约Ultra Records,2014年他创立了唱片公司Panda Funk。Deorro以前用过TON!C这个名字。Deorro的音乐倾向Melbourne Bounce风格,融合Dutch、 moombah, progressive、 house、贝斯等多种元素和风格,几分钟就可以点炸现场气氛。他的这首单曲“Five Hours”登顶Most Played on Dance Radio和Most Played on Top 40 radio Mixshows。

而在爬虫部分主要是调用官方API,本次用到的API主要有两个:

①获取评论:

http://music.163.com/api/v1/resource/comments/R_SO_4_{歌曲ID}?limit={每页限制数量}&offset={评论数总偏移}

②获取评论对应用户的信息:

https://music.163.com/api/v1/user/detail/{用户ID}

完成后的项目文件图如下:

1.1 评论爬取

具体代码如下:

1 from urllib importrequest2 importjson3 importpymysql4 from datetime importdatetime5 importre6

7 ROOT_URL = 'http://music.163.com/api/v1/resource/comments/R_SO_4_%s?limit=%s&offset=%s'

8 LIMIT_NUMS = 50 #每页限制爬取数

9 DATABASE = 'emp' #数据库名

10 TABLE = 'temp1' #数据库表名

11 #数据表设计如下:

12 '''

13 commentId(varchar)14 content(text) likedCount(int)15 userId(varchar) time(datetime)16 '''

17 PATTERN = re.compile(r'[\n\t\r\/]') #替换掉评论中的特殊字符以防插入数据库时报错

18

19 defgetData(url):20 if noturl:21 returnNone, None22 headers ={23 "User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36',24 "Host": "music.163.com",25 }26 print('Crawling>>>' +url)27 try:28 req = request.Request(url, headers=headers)29 content = request.urlopen(req).read().decode("utf-8")30 js =json.loads(content)31 total = int(js['total'])32 datas =[]33 for c in js['comments']:34 data =dict()35 data['commentId'] = c['commentId']36 data['content'] = PATTERN.sub('', c['content'])37 data['time'] = datetime.fromtimestamp(c['time']//1000)38 data['likedCount'] = c['likedCount']39 data['userId'] = c['user']['userId']40 datas.append(data)41 returntotal, datas42 exceptException as e:43 print('Down err>>>', e)44 pass

45

46 defsaveData(data):47 if notdata:48 returnNone49 conn = pymysql.connect(host='localhost', user='root', passwd='123456', db='emp', charset='utf8mb4') #注意字符集要设为utf8mb4,以支持存储评论中的emoji表情

50 cursor =conn.cursor()51 sql = 'insert into' + TABLE + '(commentId,content,likedCount,time,userId) VALUES (%s,%s,%s,%s,%s)'

52

53 for d indata:54

55 try:56 #cursor.execute('SELECT max(c) FROM '+TABLE)

57 #id_ = cursor.fetchone()[0]

58

59 cursor.execute(sql, (d['commentId'], d['content'], d['likedCount'], d['time'], d['userId']))60 conn.commit()61 exceptException as e:62 print('mysql err>>>',d['commentId'],e)63 pass

64

65 cursor.close()66 conn.close()67

68 if __name__ == '__main__':69 songId = input('歌曲ID:').strip()70 total,data = getData(ROOT_URL%(songId, LIMIT_NUMS, 0))71 saveData(data)72 iftotal:73 for i in range(1, total//50+1):74 _, data = getData(ROOT_URL%(songId, LIMIT_NUMS, i*(LIMIT_NUMS)))75 saveData(data)

实际操作过程中,网易云官方对于API的请求是有限制的,有条件的可以采用更换代理IP来防反爬,而这一次作业在爬取数据的时候由于前期操作过度,导致被BAN IP,数据无法获取,之后是通过挂载虚拟IP才实现数据爬取的。

本次采用的是单线程爬取,所以IP封的并不太频繁,后面会对代码进行重构,实现多线程+更换IP来加快爬取速度。

根据获取评论的API,请求URL有3个可变部分:每页限制数limit和评论总偏移量offset,通过API分析得知:当offeset=0时,返回json数据中包含有评论总数量total。

本次共爬取5394条数据(避免盲目多爬被封ID)

1.2 用户信息爬取

具体代码如下:

1 from urllib importrequest2 importjson3 importpymysql4 importre5

6 ROOT_URL = 'https://music.163.com/api/v1/user/detail/'

7 DATABASE = 'emp'

8 TABLE_USERS = 'temp2'

9 TABLE_COMMENTS = 'temp1'

10 #数据表设计如下:

11 '''

12 id(int) userId(varchar)13 gender(char) userName(varchar)14 age(int) level(int)15 city(varchar) sign(text)16 eventCount(int) followedCount(int)17 followsCount(int) recordCount(int)18 avatar(varchar)19 '''

20 PATTERN = re.compile(r'[\n\t\r\/]') #替换掉签名中的特殊字符以防插入数据库时报错

21 headers ={22 "User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36',23 "Host": "music.163.com",24 }25 defgetData(url):26 if noturl:27 returnNone28 print('Crawling>>>' +url)29 try:30 req = request.Request(url, headers=headers)31 content = request.urlopen(req).read().decode("utf-8")32 js =json.loads(content)33 data ={}34 if js['code'] == 200:35 data['userId'] = js['profile']['userId']36 data['userName'] = js['profile']['nickname']37 data['avatar'] = js['profile']['avatarUrl']38 data['gender'] = js['profile']['gender']39 if int(js['profile']['birthday'])<0:40 data['age'] =041 else:42 data['age'] =(2018-1970)-(int(js['profile']['birthday'])//(1000*365*24*3600))43 if int(data['age'])<0:44 data['age'] =045 data['level'] = js['level']46 data['sign'] = PATTERN.sub(' ', js['profile']['signature'])47 data['eventCount'] = js['profile']['eventCount']48 data['followsCount'] = js['profile']['follows']49 data['followedCount'] = js['profile']['followeds']50 data['city'] = js['profile']['city']51 data['recordCount'] = js['listenSongs']52

53 saveData(data)54 exceptException as e:55 print('Down err>>>', e)56 pass

57 returnNone58

59 defsaveData(data):60 if notdata:61 returnNone62 conn = pymysql.connect(host='localhost', user='root', passwd='123456', db='emp', charset='utf8mb4') #注意字符集要设为utf8mb4,以支持存储签名中的emoji表情

63 cursor =conn.cursor()64 sql = 'insert into' + TABLE_USERS + '(userName,gender,age,level,city,sign,eventCount,followsCount,followedCount,recordCount,avatar,userId) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'

65 try:66

67

68 cursor.execute(sql, (data['userName'],data['gender'],data['age'],data['level'],data['city'],data['sign'],data['eventCount'],data['followsCount'],data['followedCount'],data['recordCount'],data['avatar'],data['userId']))69 conn.commit()70 exceptException as e:71 print('mysql err>>>',data['userId'],e)72 pass

73 finally:74 cursor.close()75 conn.close()76

77 defgetID():78 conn = pymysql.connect(host='localhost', user='root', passwd='123456', db='emp', charset='utf8mb4')79 cursor =conn.cursor()80 sql = 'SELECT userId FROM'+TABLE_COMMENTS81 try:82 cursor.execute(sql)83 res =cursor.fetchall()84 returnres85 exceptException as e:86 print('get err>>>', e)87 pass

88 finally:89 cursor.close()90 conn.close()91 returnNone92

93 if __name__ == '__main__':94 usersID =getID()95 for i inusersID:96 getData(ROOT_URL+i[0].strip())97

根据获取用户信息的API,请求URL有1个可变部分:用户ID,前一部分已经将每条评论对应的用户ID也存储下来,这里只需要从数据库取用户ID并抓取信息即可(对应以上的5394条数据)。

至此,已经完成了歌曲评论和对应用户信息的抓取。接下来,对抓取到的数据进行清洗及可视化分析。

2 数据清洗 & 可视化

处理代码如下:

1 importpandas as pd2 importpymysql3 from pyecharts importBar,Pie,Line,Scatter,Map4

5 TABLE_COMMENTS = 'temp1'

6 TABLE_USERS = 'temp2'

7 DATABASE = 'emp'

8

9 conn = pymysql.connect(host='localhost', user='root', passwd='123456', db='emp', charset='utf8mb4')10 sql_users = 'SELECT id,gender,age,city FROM'+TABLE_USERS11 sql_comments = 'SELECT id,time FROM'+TABLE_COMMENTS12 comments = pd.read_sql(sql_comments, con=conn)13 users = pd.read_sql(sql_users, con=conn)14

15 #评论时间(按天)分布分析

16 comments_day = comments['time'].dt.date17 data = comments_day.id.groupby(comments_day['time']).count()18 line = Line('评论时间(按天)分布')19 line.use_theme('dark')20 line.add(21 '',22 data.index.values,23 data.values,24 is_fill=True,25 )26 line.render(r'./评论时间(按天)分布.html')27 #评论时间(按小时)分布分析

28 comments_hour = comments['time'].dt.hour29 data = comments_hour.id.groupby(comments_hour['time']).count()30 line = Line('评论时间(按小时)分布')31 line.use_theme('dark')32 line.add(33 '',34 data.index.values,35 data.values,36 is_fill=True,37 )38 line.render(r'./评论时间(按小时)分布.html')39 #评论时间(按周)分布分析

40 comments_week = comments['time'].dt.dayofweek41 data = comments_week.id.groupby(comments_week['time']).count()42 line = Line('评论时间(按周)分布')43 line.use_theme('dark')44 line.add(45 '',46 data.index.values,47 data.values,48 is_fill=True,49 )50 line.render(r'./评论时间(按周)分布.html')51

52 #用户年龄分布分析

53 age = users[users['age']>0] #清洗掉年龄小于1的数据

54 age = age.id.groupby(age['age']).count() #以年龄值对数据分组

55 Bar = Bar('用户年龄分布')56 Bar.use_theme('dark')57 Bar.add(58 '',59 age.index.values,60 age.values,61 is_fill=True,62 )63 Bar.render(r'./用户年龄分布图.html') #生成渲染的html文件

64

65 #用户地区分布分析

66 #城市code编码转换

67 defcity_group(cityCode):68 city_map ={69 '11': '北京',70 '12': '天津',71 '31': '上海',72 '50': '重庆',73 '5e': '重庆',74 '81': '香港',75 '82': '澳门',76 '13': '河北',77 '14': '山西',78 '15': '内蒙古',79 '21': '辽宁',80 '22': '吉林',81 '23': '黑龙江',82 '32': '江苏',83 '33': '浙江',84 '34': '安徽',85 '35': '福建',86 '36': '江西',87 '37': '山东',88 '41': '河南',89 '42': '湖北',90 '43': '湖南',91 '44': '广东',92 '45': '广西',93 '46': '海南',94 '51': '四川',95 '52': '贵州',96 '53': '云南',97 '54': '西藏',98 '61': '陕西',99 '62': '甘肃',100 '63': '青海',101 '64': '宁夏',102 '65': '新疆',103 '71': '台湾',104 '10': '其他',105 }106 return city_map[cityCode[:2]]107

108 city = users['city'].apply(city_group)109 city = city.id.groupby(city['city']).count()110 map_ = Map('用户地区分布图')111 map_.add(112 '',113 city.index.values,114 city.values,115 maptype='china',116 is_visualmap=True,117 visual_text_color='#000',118 is_label_show=True,119 )120 map_.render(r'./用户地区分布图.html')

关于数据的清洗,实际上在上一部分抓取数据的过程中已经做了一部分,包括:后台返回的空用户信息、重复数据的去重等。除此之外,还要进行一些清洗:用户年龄错误、用户城市编码转换等。

关于数据的去重,评论部分可以以sommentId为数据库索引,利用数据库来自动去重;用户信息部分以用户ID为数据库索引实现自动去重。

①API返回的用户年龄一般是时间戳的形式(以毫秒计)、有时候也会返回一个负值或者一个大于当前时间的值,暂时没有找到这两种值代表的含义,故而一律按0来处理。

②API返回的用户信息中,城市分为province和city两个字段,本此分析中只保存了city字段。实际上字段值是一个城市code码

③在这部分,利用Python的数据处理库pandas进行数据处理,利用可视化库pyecharts进行数据可视化。

以上,是对抓取到的数据采用可视化库pyecharts进行可视化分析,得到的结果如下:

结论一:评论时间按周分布图可以看出,评论数在一周当中前面较少,后面逐渐增多,这可以解释为往后接近周末,大家有更多时间来听听歌、刷刷歌评,而一旦周末过完,评论量马上下降(周日到周一的下降过渡),大家又回归到工作当中。

结论二:评论时间按小时分布图可以看出,评论数在一天当中有两个小高峰:11点-13点和22点-0点。这可以解释为用户在中午午饭时间和晚上下班(课)在家时间有更多的时间来听歌刷评论,符合用户的日常。至于为什么早上没有出现一个小高峰,大概是早上大家都在抢时间上班(学),没有多少时间去刷评论。

结论三:用户年龄分布图可以看出,用户大多集中在14-30岁之间,以20岁左右居多,除去虚假年龄之外,这个年龄分布也符合网易云用户的年龄段。图中可以看出28岁有个高峰,猜测可能是包含了一些异常数据,有兴趣的化可以做进一步分析。

结论四:用户地区分布图可以看出,用户涵盖了全国各大省份,因为中间数据(坑)的缺失,并没有展现出哪个省份特别突出的情况。对别的歌评(完全数据)的可视化分析,可以看出明显的地区分布差异。用户地区分布图可以看出,用户涵盖了全国各大省份,因为中间数据的缺失,并没有展现出哪个省份特别突出的情况。对别的歌评(完全数据)的可视化分析,可以看出明显的地区分布差异。

细心观察评论数(按天)分布那张图,发现2017年到2018年间有很大一部分数据缺失,这实际上是因为在数据抓取过程中出现的问题。研究了一下发现,根据获取歌曲评论的API,实际上每首歌最多只能获得2w条左右(去重后)的评论,对于评论数超过2w的歌曲,只能获得前后(日期)各1w条评论,而且这个限制对于网易云官网也是存在的,具体表现为:对一首评论数超过2w的歌,如果一直往后浏览评论,会发现从第500页(网页端网易云每页20条评论)往后,后台返回的内容和第500页完全一样,从后往前同理。这应该是官方后台做了限制,连自家也不放过。。。

此次分析只是对某一首歌曲评论时间、用户年龄/地区分布进行的,实际上抓取到的信息不仅仅在于此,可以做进一步分析(比如利用评论内容进行文本内容分析等),这部分,未来会进一步分析。当然也可以根据自己情况对不同歌曲进行分析。

3.歌评文本分析

评论的文本分析做了两部分:情感分析和词云生成。

情感分析采用Python的文本分析库snownlp。具体代码如下:

1 importnumpy as np2 importpymysql3 from snownlp importSnowNLP4 from pyecharts importBar5

6 TABLE_COMMENTS = 'temp1'

7 DATABASE = 'emp'

8 SONGNAME = 'five hours'

9

10 defgetText():11 conn = pymysql.connect(host='localhost', user='root', passwd='123456', db=DATABASE, charset='utf8')12 sql = 'SELECT id,content FROM'+TABLE_COMMENTS13 text = pd.read_sql(sql%(SONGNAME), con=conn)14 returntext15

16 defgetSemi(text):17 text['content'] = text['content'].apply(lambda x:round(SnowNLP(x).sentiments, 2))18 semiscore = text.id.groupby(text['content']).count()19 bar = Bar('评论情感得分')20 bar.use_theme('dark')21 bar.add(22 '',23 y_axis =semiscore.values,24 x_axis =semiscore.index.values,25 is_fill=True,26 )27 bar.render(r'情感得分分析.html')28

29 text['content'] = text['content'].apply(lambda x:1 if x>0.5 else -1)30 semilabel = text.id.groupby(text['content']).count()31 bar = Bar('评论情感标签')32 bar.use_theme('dark')33 bar.add(34 '',35 y_axis =semilabel.values,36 x_axis =semilabel.index.values,37 is_fill=True,38 )39 bar.render(r'情感标签分析.html')

结果:

词云生成采用jieba分词库分词,wordcloud生成词云,具体代码如下:

1 from wordcloud importWordCloud2 importmatplotlib.pyplot as plt3 plt.style.use('ggplot')4 plt.rcParams['axes.unicode_minus'] =False5

6 defgetWordcloud(text):7 text = ''.join(str(s) for s in text['content'] ifs)8 word_list = jieba.cut(text, cut_all=False)9 stopwords = [line.strip() for line in open(r'./StopWords.txt', 'r').readlines()] #导入停用词

10 clean_list = [seg for seg in word_list if seg not in stopwords] #去除停用词

11 clean_text = ''.join(clean_list)12 #生成词云

13 cloud =WordCloud(14 font_path = r'C:/Windows/Fonts/msyh.ttc',15 background_color = 'white',16 max_words = 800,17 max_font_size = 64

18 )19 word_cloud =cloud.generate(clean_text)20 #绘制词云

21 plt.figure(figsize=(12, 12))22 plt.imshow(word_cloud)23 plt.axis('off')24 plt.show()25

26 if __name__ == '__main__':27 text =getText()28 getSemi(text)29 getWordcloud(text)

词云:

python大作业报告(爬虫 分析 可视化)_爬虫综合大作业——网易云音乐《Five Hours》爬虫可视化分析...相关推荐

  1. Python的网易云音乐数据分析系统 爬虫 echarts可视化 Flask框架 音乐推荐系统 源码下载

    Python的网易云音乐数据分析系统 爬虫 echarts可视化 Flask框架 音乐推荐系统 一.技术说明 网易云音乐数据(歌单.用户.歌词.评论)Python爬取Flask框架搭建ECharts. ...

  2. python爬虫网易云音乐最热评论并分析_Python3实现爬虫抓取网易云音乐的热门评论分析(图)...

    这篇文章主要给大家介绍了关于Python3实战之爬虫抓取网易云音乐热评的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧. ...

  3. Python爬虫实战,matplotlib模块,Python实现网易云音乐歌单数据可视化

    前言 利用Python实现网易云音乐歌单数据可视化.废话不多说. 让我们愉快地开始吧~ 开发工具 Python版本: 3.6.4 相关模块: requests模块 pandas模块 matplotli ...

  4. python爬虫网易云音乐最热评论并分析_python爬虫入门 实战(三)---爬网易云音乐热门评论...

    网易云音乐 本篇涉及知识: 1.request第三方库的基本使用 2.json解析 本篇目标: 爬取指定一个歌单的所有歌曲的热门评论 (注:本篇爬取不直接解析html文本,而是直接分析获取评论的api ...

  5. 简单的网易云音乐热门评论爬虫

    简单的网易云音乐热门评论爬虫 注:本文没有什么技术含量,就是一个普通的AJAX数据爬虫,适合新手练习 目标:爬取网易云音乐歌曲的热门评论 分析:本次爬虫不难,思路是请求和获取数据,网易云音乐的评论是通 ...

  6. python爬虫网易云音乐最热评论并分析_网易云音乐热门评论api分析

    网上有现成的例子我就扒过来了!! title: 网易云评论api分析 date: 2018-12-24 20:54:46 tags: [python] 网易云音乐是个好地方,里面各个都是人才,特别是评 ...

  7. python可视化分析网易云音乐评论_Python数据可视化:网易云音乐歌单

    通过Python对网易云音乐华语歌单数据的获取,对华语歌单数据进行可视化分析. 可视化库不采用pyecharts,来点新东西. 使用matplotlib可视化库,利用这个底层库来进行可视化展示. 推荐 ...

  8. python网易云听歌时长_用Python爬取10w条网易云音乐热评并进行分析的方法总结

    有个段子讲"十年文案老司机,不如网易评论区,网易文豪遍地走,评论全部单身狗",网易云音乐的评论区也一直都是各类文案大神的聚集地. 那么我们普通用户到底如何成为网易云音乐评论里的热评 ...

  9. python爬取网易云音乐评论并进行可视化分析

    2019独角兽企业重金招聘Python工程师标准>>> 前言 今天为大家一个爬取网易云音乐评论的Python案例,并用Python的第三方库来进行可视化分析,生成图表样式,可以清晰地 ...

  10. Python爬虫之js加密破解,抓取网易云音乐评论生成词云

    js破解历程 前言 技能点 界面概况 静态网页动态网页 页面解析 step1: 找参数step2:分析js函数step3:分析参数step4: 校验step5:转为python代码 编写爬虫 很多人学 ...

最新文章

  1. MOSES | 分子生成模型的基准平台
  2. 图像处理之霍夫变换(直线检測算法)
  3. rop的noejs客户端
  4. FortiGate设置E-mail告警
  5. 使用goJenkins create job 返回500
  6. 重学java基础第二十四课:标识符合关键字
  7. 前端学习(1343):集合关联
  8. 计算机主机和cpu的区别,服务器CPU和普通电脑CPU有什么区别?
  9. 命令行shell 用于SQLite
  10. 去掉右键新建菜单多余内容
  11. 1.linux系统基础笔记(互斥量、信号量)
  12. M1 Max 暴击,倚天补刀
  13. 这个网站还不错,可以多看看(这个是学习的网站,没有广告)
  14. paip.文件读写api php java python总结.txt
  15. eclipse 类文件编辑器找不到源的问题
  16. JMeter基础 — JMeter中BeanShell断言详解
  17. 无需备份!!!动态磁盘转换为基本磁盘!!!绝对可用!!!
  18. 对称与非对称密钥加密
  19. (附源码)springboot垃圾自动分类管理系统 毕业设计 160846
  20. 每日新闻早报简报十条和1条微语分享

热门文章

  1. AutoCAD2021使用方法与小技巧总结1
  2. 论文阅读:Volumetric and Multi-View CNNs for Object Classification on 3D Data
  3. canvas——绘制解锁图案
  4. 如何升级变色龙本体 AVR 固件
  5. ECCV 2022,两位华人学者摘得最佳论文奖,本科来自清华、浙大
  6. 【计算机基础】文件存储单位及其换算
  7. 工商管理论文要怎么写?
  8. 蓝桥---超声波测距
  9. [精简]托福核心词汇53
  10. LinkCloud引领云主机免申请免费试用潮流