Python高级应用程序设计任务要求


用Python实现一个面向主题的网络爬虫程序,并完成以下内容:
(注:每人一题,主题内容自选,所有设计内容与源代码需提交到博客园平台)

一、主题式网络爬虫设计方案(15分)

1.主题式网络爬虫名称

爬取qq音乐歌手信息

2.主题式网络爬虫爬取的内容与数据特征分析
爬取qq音乐歌手歌曲数量及专辑的年代分布
 
3.主题式网络爬虫设计方案概述(包括实现思路与技术难点)
      requests库对目标页面进行爬取,发现目标数据是json数据类型,用json解析成字典后直接依照key-value值对数据进行抓取。xlwt将数据存入.xls文件,pandas读取文件数据,
分别用matplotlib对数据进行折线图,饼图,条形图的绘制并进行保存。
 
二、主题页面的结构特征分析(15分)
1.主题页面的结构特征
https://c.y.qq.com/soso/fcgi-bin/client_search_cp?&remoteplace=txt.yqq.album&t=8&p={page}&n=5&w={singername}&format=json
此为数据页面的url,通过修改page和singername字段获取不同的数据

2.Htmls页面解析
可以发现所需数据是son数据类型。

3.节点(标签)查找方法与遍历方法。
        js = json.loads(html)
        # 定位到albumTime和albumCount
        albumlist = js['data']['album']['list']
        for song in albumlist:
            #获取年代值
            albumtime = song['publicTime']
            #获取歌曲量值
            albumsongs = song['song_count']
            #判断歌曲年份,将符合条件的值加入value中。
            if eval(albumtime.split('-')[0]) in all_albumcount:
                temp = eval(albumtime.split('-')[0])
                all_albumcount[temp] += eval(str(albumsongs))

 转换成字典后,用访问键值对的形式对所需数据进行提取。


(必要时画出节点树结构)
 
三、网络爬虫程序设计(60分)
爬虫程序主体要包括以下各部分,要附源代码及较详细注释,并在每部分程序后面提供输出结果的截图。
 
  1 import requests
  2 import json
  3 import xlwt
  4 import pandas as pd
  5 import matplotlib.pyplot as plt
  6
  7
  8 def catchhtml(url):
  9     kv = {'Cookie': 'pgv_pvid=7162285489; pac_uid=0_0be1d8bfa215f; eas_sid=11Y5e6u2S2o4n3u2t0q359I978; LW_uid=j1m5M6g2c2j4j3A2F0E4b0B0J9; pgv_pvi=4853538816; RK=tBYotsT5Zq; ptcz=9e72248cfd67ff6067546c003c95d477ee46b6b1a3494f7c7bfaf9ed453324fc; LW_sid=01K5i6X2l2r4h3j2k0X7z087Q8; ts_refer=www.baidu.com/link; ts_uid=8369992458; yq_index=0; pgv_info=ssid=s259050750; pgv_si=s9332981760; userAction=1; _qpsvr_localtk=0.2090326051426059; ptisp=ctc; yqq_stat=0; ts_last=y.qq.com/; ptui_loginuin=2083297662; psrf_qqopenid=C9571221E6F57F469D4806675329EC6C; uin=2083297662; psrf_qqrefresh_token=80A6D34A4886D7897F39F64C0EF5D01A; psrf_qqunionid=FB55EE2FEAAF3583D03C9DD7A3E96DEB; psrf_musickey_createtime=1574075120; qm_keyst=Q_H_L_20lUIt50eit-NhzzjPvrMhPlEWfyV7Lr-j0Neg_NyYMxWmYBVB9MMVydv_-ZHT3; psrf_qqaccess_token=E362E4122C8BCA86BC5250BC7465E896; psrf_access_token_expiresAt=1581851120',
 10           'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36'}
 11     #错误异常判断
 12     try:
 13         data = requests.get(url, headers=kv, timeout=30)
 14         data.raise_for_status()
 15         data.encoding = data.apparent_encoding
 16         return data.text
 17     except:
 18         return "爬取失败"
 19
 20
 21 def getdata(times, singer):
 22     #存储歌曲年代和数量的字典
 23     all_albumcount = {}
 24     for i in range(1999, 2020):
 25         all_albumcount[i] = 0
 26     for num in range(1, times):
 27         #获取信息的目标url
 28         url = f'https://c.y.qq.com/soso/fcgi-bin/client_search_cp?&remoteplace=txt.yqq.album&t=8&p={num}&n=5&w={singer}&format=json'
 29         html = catchhtml(url)
 30         # 将请求到json数据解析为字典
 31         js = json.loads(html)
 32         # 定位到albumTime和albumCount
 33         albumlist = js['data']['album']['list']
 34         for song in albumlist:
 35             #获取年代值
 36             albumtime = song['publicTime']
 37             #获取歌曲量值
 38             albumsongs = song['song_count']
 39             #判断歌曲年份,将符合条件的值加入value中。
 40             if eval(albumtime.split('-')[0]) in all_albumcount:
 41                 temp = eval(albumtime.split('-')[0])
 42                 all_albumcount[temp] += eval(str(albumsongs))
 43     return all_albumcount
 44
 45
 46 #将数据存入文件
 47 def write_file(data, saveurl):
 48     # 创建Workbook,相当于创建Excel
 49     book = xlwt.Workbook(encoding='utf-8')
 50
 51     # 创建sheet,Sheet1为表的名字,cell_overwrite_ok为是否覆盖单元格
 52     sheet1 = book.add_sheet(u'Sheet1', cell_overwrite_ok=True)
 53
 54     #写入列名
 55     sheet1.write(0, 0, 'year')
 56     sheet1.write(0, 1, 'songs')
 57     r = 1
 58     # i表示data中的key,j表示data中的value
 59     for i, j in data.items():
 60         sheet1.write(r, 0, i)
 61         sheet1.write(r, 1, j)
 62         r += 1
 63     book.save(saveurl)
 64     print(f'写入文件成功,地址为{saveurl}')
 65
 66
 67 #读取文件
 68 def read_file(singer):
 69     try:
 70         data = pd.read_excel(f'D:/{singer}.xls', names=['year', 'songs'])
 71         print('读取文件成功')
 72         return data
 73     except:
 74         "文件不存在或文件名错误"
 75
 76
 77 #折线图
 78 def ChartBroken(x, y):
 79     #图片在额外的窗口显示
 80     plt.figure()
 81     plt.plot(x, y)
 82     #y轴命名
 83     plt.ylabel('Songs')
 84     #x轴命名
 85     plt.xlabel('Year')
 86     plt.axis([2000, 2020, 0, 200])
 87     plt.title('Brokenplot')
 88     # 保存程序结果,数据持久化
 89     plt.savefig('Broken', dpi=600)
 90     print('折线图保存成功')
 91     plt.show()
 92
 93 #饼图
 94 def ChartPie(listx):
 95     plt.figure()
 96     labels = '2000-2004', '2005-2009', '2010-2014', '2015-2019'
 97     sizes = [sum(listx[:4]), sum(listx[5:9]), sum(listx[10:14]), sum(listx[15:19])]
 98     explode = (0, 0, 0, 0)
 99     plt.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%'
100             , shadow=False, startangle=90)
101     plt.axis('equal')
102     # 保存程序结果,数据持久化
103     plt.title('Pieplot')
104     plt.savefig('Pie', dpi=600)
105     print('饼图保存成功')
106     plt.show()
107
108 #条形图
109 def ChartBar(xaxis, yaxis):
110     plt.figure()
111     plt.bar(left=xaxis, height=yaxis, color='b', width=0.5)
112     plt.ylabel('Songs')
113     plt.xlabel('Year')
114     plt.title('Barplot')
115     # 保存程序结果,数据持久化
116     plt.savefig('Bar', dpi=600)
117     print('条形图保存成功')
118     plt.show()
119
120 #主函数
121 def main():
122     # 20页,每页5张专辑
123     times = 20
124     singer = '陈奕迅'
125     datadict = getdata(times, singer)
126
127     # 数据保存位置(根据歌手名称)
128     saveurl = f'D:\\{singer}.xls'
129     write_file(datadict, saveurl)
130     # 读取excel文件
131     data = read_file(singer)
132     # 根据列名拆分为多组Series
133     year = data['year']
134     songs = data['songs']
135
136     ChartBroken(year, songs)
137     ChartPie(songs)
138     ChartBar(year, songs)
139
140
141 if __name__ == '__main__':
142     main()

运行结果如下:

 
四、结论(10分)
1.经过对主题数据的分析与可视化,可以得到哪些结论?
对歌手的歌曲年代分布和歌曲数量之间的关系有了明确的认知。
陈奕迅的歌曲产出分布主要是00-13年间,近几年的出曲量较少。

2.对本次程序设计任务完成的情况做一个简单的小结
对数据爬取和可视化的结合有了一个大致的一体化概念,大数据时代,数据的可视化的确十分重要,能更直观的观察数据变化等。
任务的完成度还算可以吧,也增大了我对爬虫的兴趣,过程中发现了一些其他的好玩的用途,没使用到一些库有些可惜,但是需求的数据就是那种形式的也没办法,
这次没怎么使用过的东西会在其他的地方去熟悉一下。
 
12-24 02:52
查看更多