Python爬虫与数据分析
Python爬虫与数据分析
- 目的
爬取网易云音乐歌曲热评,分析热评特征。 - 思路
(1)爬取华语歌单中所有歌单url
(2)从每篇歌单地址中爬取每首歌的url
(3)从每首歌的首页爬取热评 - 代码
(1) 爬取华语歌单中所有歌单url,从歌单url获取歌单中每首歌的歌名和id,并保存到文件music_163_02.csv。
import logging
import requests
from pyquery import PyQuery as pq
import pandas as pd
import random
import time# headers需要填上,否则无法正常爬取
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'}
# 设置日志的格式、输出级别
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s: %(message)s')def scrape_index(url):response = requests.get(url,headers = headers )logging.info('scrape index %s...',url) #不需要再url前加%,而是,try:if response.status_code == 200: return parse_index(response.text) # 传到parse_index 方法中获取歌单url列表else :logging.error('invaild status is %s while scraping url %s', response.status_code, url)except Exception:logging.error('error occurred while scraping %s', url, exc_info=True) # exc_info=True:会将异常异常信息添加到日志消息中 def parse_index(html):doc = pq(html) # 用pyquery进行解析 a = doc('#m-pl-container .dec .s-fc0') # #对应div .对应classa1 = a.items() # 对于返回值是多个元素,然后对每个元素做处理,需要调用items方法,返回的generator类型,可以通过for 循环去取值return a1def scrape_detail(url):response = requests.get(url,headers = headers )logging.info('scraping detail %s...',url)try:if response.status_code == 200:logging.info('detail url is succeed ')return parse_detail(response.json()) # API获取的内容返回的是json格式else:logging.error('invaild status is %s while scraping url %s', response.status_code, url)except Exception:logging.error('error occurred while scraping %s', url, exc_info=True)'''
热评获取API:http://music.163.com/api/v1/resource/comments/R_SO_4_{歌曲ID}?limit=20&offset=0
所以获取歌曲的ID就可以得到热评
'''
def parse_detail(html):list_02 = []jobs = html['result']['tracks']for j in jobs:dic ={}dic['name'] = j['name'] # 创建 字典dic['id'] = j['id']list_02.append(dic) return list_02 def get_list():list_01 = []url = 'https://music.163.com/discover/playlist/?order=hot&cat=%E5%8D%8E%E8%AF%AD&limit=35&offset={page}'for page in range(0,35,35): # 跑一页试试,如果跑全部,改为 range(0,1295,35)url1 = url.format(page = page)list = []for i in scrape_index(url1): # generator 遍历之后的i的类型仍然是qyquery类型i_url = i.attr('href') # attr 方法来获取属性'''获取歌单和评论均用了网易云音乐get请求的API,快速高效!网易云歌单APIhttps://music.163.com/api/playlist/detail?id={歌单ID}热评获取APIhttp://music.163.com/api/v1/resource/comments/R_SO_4_{歌曲ID}?limit=20&offset=0'''detail_url = f'https://music.163.com/api{i_url.replace("?","/detail?")}' #获取的url还需要替换一下符合API要求的格式list.append(detail_url) list_01.extend(list) # extend 对列表合并 time.sleep(5+random.random()) # 文明爬虫return list_01df = pd.DataFrame(columns = ('name','id'))def save_date(list):df1 = pd.DataFrame(list)df2 = pd.concat([df, df1])df3 = df2.drop_duplicates(subset=None, keep='first',inplace = False) df3.to_csv('G:/work/01_project/05_Data/music_163_02.csv',index_label="index_label", encoding='utf-8-sig') # index_label索引列的列标签def main():detail_list = []url_01 = get_list()for l in url_01:logging.info('detail url is %s',l)detail_list_part = scrape_detail(l) detail_list.extend(detail_list_part) # 列表合并,得到最后的完整歌单信息列表time.sleep(5+random.random()) save_date(detail_list) if __name__ == '__main__':main()
(2)获取每首歌的url,从首页得到热评信息
import pandas as pd
import requests
import logging
import time
import randomheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'}
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s: %(message)s')def scrape_comment(url, name):logging.info('scraping comments %s',url)try:response = requests.get(url, headers = headers)if response.status_code == 200:return parse_comment(response.json(), name ) # 网易云热评API返回的是json格式else :logging.error('invaild status_code %s while scraping %s',response.status_code, url)except Exception:logging.error('can not scraping %s', url)def parse_comment(html, name ):data = []jobs = html['hotComments']for job in jobs:dic = {}dic['nickname'] = job['user']['nickname']dic['userid'] = job['user']['userId']dic['content'] = job['content'].replace('\n', '') # 对换行符进行替换 dic['likecount'] = job['likedCount']dic['time'] = stampToTime(job['time']) # 时间戳的转换dic['name'] = namedata.append(dic)return data def stampToTime(stamp):'''获得是13位的时间戳,需要转化成时间字符串将ms(毫秒)转成s(秒) stamp/1000将10位的符合python的时间戳转化成时间元组,localtime():北京时间将时间元组用strftime转化成时间字符串'''timeStamp = float(stamp/1000) timeArray = time.localtime(timeStamp)date = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)return datedef main():df = pd.read_csv('G:/work/01_project/05_Data/music_163_02.csv',header = 0) # 对上个保存的歌曲的ID的csv的内容提取,header= 0:第一行作为columndata_comment = []for index,row in df.iterrows(): # 数据框中的行 进行迭代的一个生成器,它返回每行的索引及一个包含行本身的对象。name = row['name']url = f'http://music.163.com/api/v1/resource/comments/R_SO_4_{row["id"]}?limit=20&offset=0' # 本文只爬取首页(第一页)的热评data1 = scrape_comment(url, name) data_comment.extend(data1) df1 = pd.DataFrame(data_comment)df1.to_csv('G:/work/01_project/05_Data/hotComments_06p.csv',encoding = 'utf-8-sig') # 是utf-8-sig 而不是utf-8logging.info('scraping id %s',index)time.sleep(random.random()) # 文明爬虫if __name__ == '__main__':main()
代码思路总结
爬虫实际是模拟人对网页信息进行获取,而代码则替代人工,快速且可暴力循环的,解析并爬取互联网的大量信息。(个人简单理解)从思路中分析,提出以下问题:
(1)如何爬取华语歌单中所有歌单url,并从每篇歌单地址中爬取每首歌的url?(代码块1实现,Python包是工具包)
步骤如下:
a、进入华语歌单url,循环获取每一页歌单里的每个歌单url ,歌单url用pyquery进行解析html进行获取,获取的url需要替换成符合API要求的格式,将每一页的API列表进行合并。
b、从歌单API列表中用requests得到响应的json,解析json获取想要得到的所有歌曲key和value,将这些key和value放入字典,将这些字典放入列表中,得到的列表是一个歌单里的歌曲列表,将每个歌单的歌曲列表合并。
c、得到歌曲列表的歌名和url的id值,保存数据到文件music_163_02.csv。
(2)如何从每首歌的首页爬取热评?(代码块2实现,Python包是工具包)
步骤如下:
a、读取文件music_163_02.csv获取歌曲id和名字,热评API中加入歌曲id,只爬取第一页的热评。用requests得到响应的json,从json中获取具体的评论,评论列表合并。
- 数据清洗、数据获取与数据分析
(1)数据清洗与具体数据获取
import matplotlib.pyplot as plt
import pandas as pd
import jieba
import jieba.analyse
import numpy as np
from PIL import Image
from wordcloud import WordCloud'''
发现也是因为csv文件中单个item内有\r,即回车符
解决方法:lineterminator=”\n”:让\n作为换行符即可
'''
df3 = pd.read_csv('G:/work/01_project/05_Data/hotComments_06p.csv',index_col = 0,lineterminator='\n')# 用strip()方法去除开头或则结尾的空格
df3['content1'] = df3['content'].apply(lambda x:x.strip())# 有些句子中有\r,因为我们以\n作为换行符,所以这些\r不属于文本,需要去掉
df3['content1'] = df3['content'].apply(lambda x:x.replace('\r', ''))
df4 = df3.drop(['content'],axis=1)
df4.rename(columns = {'content1':'content'},inplace = True)
df4['name1'] = df4['name\r'].apply(lambda x:x.replace('\r', ''))
df5 = df4.drop(['name\r'], axis=1)
df5.rename(columns = {'name1':'name'}, inplace=True)
df5# 对点赞数排序
df6 = df5.sort_values(by = 'likecount', ascending=False)
#df6.head(10)['content']
df6.head(10).to_csv('G:/work/01_project/05_Data/strat_TOP10.csv', index=False, encoding = 'utf-8-sig')
df6
# 对重复的句子次数排序
df7 = df5.groupby('content').size().sort_values(ascending=False).reset_index(name='count')
df7
(2)数据分析
#热评最多的ID都有那些特征
df8 = df5.groupby('userid').count().sort_values(by='content',ascending=False)
df8
# 热评最多的Id 是 626970848
from matplotlib.font_manager import FontProperties
font_set = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=15)df9 = df5[df5['userid'] == 626970848]plt.hist(df9['likecount'], bins = 200, density = True )
plt.xlim((0,70000))
plt.title('用户的点赞分布', fontproperties=font_set)
plt.show()df9
df10 = df9['content'].map(len) # map函数进行求取每一单元格个长度
plt.hist(df10, bins = 20, density = True)
plt.title('626970848用户的评论长度分布', fontproperties=font_set)
plt.show()df10
热评最多的用户点赞数集中分布在10000以下,几千几百的最多,侧面说明了这些歌曲是比较小众的,可能在新歌区广撒网评论。评论长度集中在60字以下,侧面说明短评获取关注度更多。
热评的频次较多的词语有哪些?
'''jieba库中基于 TextRank 算法的关键词抽取详情见官方文档:https://github.com/fxsjy/jieba
'''
segments = []
for index,row in df4.iterrows(): content = row[5]words = jieba.analyse.textrank(content,topK=3, withWeight=False,allowPOS=('ns', 'n', 'vn', 'v'))for w in words: # 对分词好后的words进行提取,并且关联一个1,方便进行计数segments.append({'word':w,'counts':1})
df_w = pd.DataFrame(segments)df_w.to_csv('G:/work/01_project/05_Data/jieba_01.csv',index = False,encoding = 'utf-8-sig')
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator text = ' '.join(df_w['word'])mask_cir = np.array(Image.open('G:/work/01_project/05_Data/2222.png')) wordc =WordCloud(background_color='white',mask = mask_cir,font_path = 'G:/work/01_project/05_Data/simhei.ttf', # 中文显示的方法,baidu载一个SimHei.ttf字体包即可让云词显示中文max_words=1000).generate(text)
plt.imshow(wordc)
plt.axis('off')plt.show()
将所有热评绘制成词云,发现“喜欢”与“首歌”这两个词汇被最多提及。还有其他“感觉”、“大哭”、“女孩”等,也许大部分人都经历过的两件事,就是年少懵懂的倾慕与深夜崩溃的瞬间。
本文学习知乎链接实战(其代码有部分缺少以及错误):https://zhuanlan.zhihu.com/p/143188410?utm_source=wechat_session
Python爬虫与数据分析相关推荐
- 【爬虫+数据可视化毕业设计:英雄联盟数据爬取及可视化分析,python爬虫可视化/数据分析/大数据/大数据屏/数据挖掘/数据爬取,程序开发-哔哩哔哩】
[爬虫+数据可视化毕业设计:英雄联盟数据爬取及可视化分析,python爬虫可视化/数据分析/大数据/大数据屏/数据挖掘/数据爬取,程序开发-哔哩哔哩] https://b23.tv/TIoy6hj
- Python 爬虫和数据分析实战
课程介绍 本课程以一个小项目带你快速上手 Python 爬虫和数据分析,主要分 3 部分: 第 1 部分是 Python 爬虫,主要使用 Urllib 3 和 BeautifulSoup 抓取天猫商城 ...
- 毕业设计 python爬虫基础+数据分析
学习目标: 完成内容:python爬虫基础+数据分析(3.23-4.10) 6天学会数据可视化内容 4月10号完成毕设论文 [如果没有被免毕业设计的话] 学习内容: 软件安装 安装python3.10 ...
- 【【数据可视化毕业设计:差旅数据可视化分析,python爬虫可视化/数据分析/大数据/大数据屏/数据挖掘/数据爬取,程序开发-哔哩哔哩】-哔哩哔哩】 https://b23.tv/iTt30QG
[[数据可视化毕业设计:差旅数据可视化分析,python爬虫可视化/数据分析/大数据/大数据屏/数据挖掘/数据爬取,程序开发-哔哩哔哩]-哔哩哔哩] https://b23.tv/iTt30QG ht ...
- Python爬虫、数据分析、可视化学习笔记(一、梦开始的地方)
系列文章持续更新中...... 文章目录 一.工具及环境配置 1.Python3.8(官网下载) 2.Pycharm(官网下载) 3.Anaconda(官网下载) 4.环境配置(传送门,感谢前人栽树) ...
- 6张脑图系统讲透python爬虫和数据分析、数据挖掘
1.python爬虫:比较详细介绍了爬虫所需要具备的库.工具.爬虫基础知识 2.python爬虫流程 3.python数据分析简介 4.python数据预处理方法 5.python数据挖掘基础 6.p ...
- python爬虫和数据分析电脑推荐_大数据分析必备的5款Python爬虫库
在数据科学或人工智能领域,除了算法之外,最重要的应该是数据了.甚至可以说一个模型到最后决定其准确度的往往不是算法而是数据.在现实中,缺少足够的数据成了数据分析师获得优秀模型的主要阻碍.可喜的是,现在网 ...
- 基于 Python 爬虫+简单数据分析的课程设计(附PPT)
按照课程设计要求,要用python做一个关于数据分析的小项目,在这里我们选的是爬取豆瓣图书TOP250,其中用到一些常用的数据处理及可视化方法,比如Echarts.Flask等! PPT部分截图: 报 ...
- 全网最全python爬虫+数据分析资源整理
4.29(第二天) 开篇词 你为什么需要数据分析能力? 第一模块:数据分析基础篇 (16讲) 01丨数据分析全景图及修炼指南 02丨学习数据挖掘的最佳路径是什么? 03丨Python基础语法:开始你的 ...
最新文章
- 高性能 Java 应用层网关设计实践
- qt mysql显示文件名字_【实例】Qt获取文件属性
- 让Windows 2000/XP系统自动登陆
- 深入理解Java虚拟机--中
- 组合数学:容斥原理(HDU1976)
- html5画图论文结束语,基于HTML5 Canvas的画图板的设计与实现.doc
- Arduino十大滤波算法程序大全(精编无错版)
- 人工神经网络之Python 实战
- .net core 图片合并,图片水印,等比例缩小,SixLabors.ImageSharp
- 利用函数imnoise2处理噪声污染和spfilt处理滤波器
- Real Estate Photography: Exterior at Twilight 房地产摄影:暮光之城 Lynda课程中文字幕
- Android源码在线查看工具
- linux系统编译Q,Linux下安装qBittorrent,开启24小时挂机BT下载
- java中CheckException和UnCheckException的区别
- python古诗词生成_Python一日一练02----诗词生成器
- 后缀为.epub的是什么格式的文件
- b区机械考研哪些院校比较好考?
- 利用ajax从jsp中返回的字符串时出现回车符号解决办法
- 电商API店铺订单接口(代码对接教程)
- 《我是一只IT小小鸟》连载五
热门文章
- 2020年c语言二级考试题库免费,2020年国家级计算机等级考试二级C语言考试试题库.pdf...
- 如何使用蓝牙实现OTA固件升级
- Java打印int类型二进制
- 一篇文章让你搞懂Java中的静态代理和动态代理
- 基于jQuery的2048游戏
- 木桶原则(计算机,新木桶原则
- keil编程时 error: #65: expected a “;“ 的解决办法
- 使用Origin进行非线性高斯拟合
- spring之所以不用new对象!
- A10-7860K试装DSM