Python高级应用程序设计任务

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

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

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

   B站番剧页面数据的爬取与分析

2.主题式网络爬虫爬取的内容与数据特征分析

    获取B站单个页面的视频信息,包括av号、上传者、上传时间、观看人数、弹幕数、分享数、排名等
3.主题式网络爬虫设计方案概述(包括实现思路与技术难点)

实现思路:使用requests库爬取数据,使用matplotlib模块实现数据可视化

技术难点:B站数据的爬取和破解B站反爬

二、主题页面的结构特征分析(15分)
1.主题页面的结构特征

主体页面为B站的番剧页面,分为网页头部、网页中部、网页尾部、其中有用的数据在网页中部的有用信息,
2.Htmls页面解析

Python高级应用程序设计任务

 

 

 


3.节点(标签)查找方法与遍历方法
(必要时画出节点树结构)

Python高级应用程序设计任务

 

 

三、网络爬虫程序设计(60分)
爬虫程序主体要包括以下各部分,要附源代码及较详细注释,并在每部分程序后面提供输出结果的截图。
1.数据爬取与采集

# 导入对应的 package
import numpy as np
import pandas as pd
import requests
import time


def get_data(base_url, page):

    url = base_url.format(str(page))  # 得到对应的url
    response = requests.get(url, headers=header)  # 发出请求,获取回应
    response.encoding="utf-8"
    videos = pd.read_json(response.text[37:-1]).iloc[:, 3].iloc[0]  # 获取列表
    videos_list = []  # 用来储存数据
    for video in videos:  # 循环每个番剧
        video_inf = []  # 用来储存每个番剧的信息
        video_inf.append(video['stat']['aid'])  # av号
        video_inf.append(video["title"])  # 标题
        video_inf.append(video['owner']["name"])  # 上传者
        video_inf.append(time.ctime(video['pubdate']))  # 上传时间

        video_inf.append(video['stat']['view'])  # 观看人数
        video_inf.append(video['stat']['danmaku'])  # 弹幕数
        video_inf.append(video['stat']['reply'])  # 评论数量
        video_inf.append(video['stat']['favorite'])  # 收藏数量
        video_inf.append(video['stat']['coin'])  # 投币数
        video_inf.append(video['stat']['share'])  # 分享数
        video_inf.append(video['stat']['like'])  # 点喜欢的人数
        video_inf.append(video['stat']['dislike'])  # 点不喜欢的人数
        video_inf.append(video['stat']["now_rank"])  # 排名
        video_inf.append(video['stat']["his_rank"])  # 排名

        video_inf.append(video['tname'])  # 标签
        video_inf.append(video['desc'])  # 描述

        videos_list.append(video_inf)
    return videos_list


def get_all_data(n):

    # 数据对应的列名
    col = ['av号', '标题', 'up主', '上传日期', '观看次数', '弹幕', 'reply',
           '收藏', '投币', '分享', '喜欢', '不喜欢', '现在排名', '他的排名', '标签', '描述']
    # 建立 DataFrame 来储存数据
    data = pd.DataFrame(columns=col)

    # 循环页数
    for i in range(1, n + 1):
        data_temp = pd.DataFrame(
            get_data(base_url, i), columns=col)  # 对应页的数据,临时储存
        data = pd.concat([data, data_temp], axis=0,
                         ignore_index=True)  # 与之前的数据合并在一块
        # 适当的停顿,防止请求过快,封ip
        time.sleep(np.random.rand() * np.random.randint(1, 3))
    return data



base_url = "https://api.bilibili.com/x/web-interface/newlist?callback=jqueryCallback_bili_4431985766884974&rid=33&type=0&pn={}&ps=20&jsonp=jsonp&_=1558156016281"
# 一些的请求头,伪装成浏览器,可以防止一些反爬虫的机制
header = {"Referer": "https://www.bilibili.com/v/anime/serial/?spm_id_from=333.334.b_7072696d6172795f6d656e75.8",
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"}


data = get_all_data(1325)  # 获取1325页的视频数据,页数为网页直接查看获得
filename='bilibili_data1.csv'
data.to_csv(filename,encoding="utf-8")

 


2.对数据进行清洗和处理

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
data = pd.read_csv('C:/Users/3号/PycharmProjects/biliHello/bilibili_data.csv')
data.head()

# 首先查看下数据是否有 nan 值
data.isnull().sum()
查看是哪一行
data[data.isnull()['up主']]
# 去掉这一行
data.drop(26397, inplace=True)
# 查看数据有没有重复项
data.duplicated().sum()
# 确认下最小值
data.min()
# 将上传时间 转换成 datetime 类型
data['上传日期'] = pd.to_datetime(data['上传日期'])
# 查看一下统计
data.describe()

Python高级应用程序设计任务

 

 

 Python高级应用程序设计任务

 

 

 Python高级应用程序设计任务

 

 

 


3.文本分析(可选):jieba分词、wordcloud可视化


4.数据分析与可视化

(例如:数据柱形图、直方图、散点图、盒图、分布图、数据回归分析等)

# 看一下各数据的相关性
data.corr()

Python高级应用程序设计任务

 

 

 

# 查看up主投稿的数量
data.groupby("up主").count().sort_values("av号", ascending=False)  # 根据up主投稿的数量排序

Python高级应用程序设计任务

data.sort_values("观看次数", ascending=False).reset_index(drop=True)['观看次数'].plot()

Python高级应用程序设计任务

 

 

 

# 查看投币排序
data.sort_values("投币", ascending=False).reset_index(drop=True)['投币'].plot()

Python高级应用程序设计任务

 

 

 

# 查看一下根据投稿时间的播放量情况
plt.plot(data.set_index("上传日期")['观看次数'].sort_index())
plt.title(u'播放量', fontproperties=font_hei)

Python高级应用程序设计任务

 

 

 

 

5.数据持久化

Python高级应用程序设计任务

 

 

 

Python高级应用程序设计任务

 

 

 


6.附完整程序代码

1.获取B站HTML源码
import requests
from bs4 import BeautifulSoup
url='https://www.bilibili.com/v/anime/serial/#/all/default'
def getHTMLText(url,timeout=30):
  try:
      r=requests.get(url,timeout=30)
      r.raise_for_status()
      r.enconding=r.apparent_encoding
      return r.text
  except:
      return '产生异常'
html=getHTMLText(url)
soup=BeautifulSoup(html,'html.parser')
print(soup.prettify())
2.获取B站番剧数据
# 导入对应的 package
import numpy as np
import pandas as pd
import requests
import time


def get_data(base_url, page):

    url = base_url.format(str(page))  # 得到对应的url
    response = requests.get(url, headers=header)  # 发出请求,获取回应
    response.encoding="utf-8"
    videos = pd.read_json(response.text[37:-1]).iloc[:, 3].iloc[0]  # 获取列表
    videos_list = []  # 用来储存数据
    for video in videos:  # 循环每个番剧
        video_inf = []  # 用来储存每个番剧的信息
        video_inf.append(video['stat']['aid'])  # av号
        video_inf.append(video["title"])  # 标题
        video_inf.append(video['owner']["name"])  # 上传者
        video_inf.append(time.ctime(video['pubdate']))  # 上传时间
        video_inf.append(video['stat']['view'])  # 观看人数
        video_inf.append(video['stat']['danmaku'])  # 弹幕数
        video_inf.append(video['stat']['reply'])  # 评论数量
        video_inf.append(video['stat']['favorite'])  # 收藏数量
        video_inf.append(video['stat']['coin'])  # 投币数
        video_inf.append(video['stat']['share'])  # 分享数
        video_inf.append(video['stat']['like'])  # 点喜欢的人数
        video_inf.append(video['stat']['dislike'])  # 点不喜欢的人数
        video_inf.append(video['stat']["now_rank"])  # 排名
        video_inf.append(video['stat']["his_rank"])  # 排名
        video_inf.append(video['tname'])  # 标签
        video_inf.append(video['desc'])  # 描述
        videos_list.append(video_inf)
    return videos_list
def get_all_data(n):

    # 数据对应的列名
    col = ['av号', '标题', 'up主', '上传日期', '观看次数', '弹幕', 'reply',
           '收藏', '投币', '分享', '喜欢', '不喜欢', '现在排名', '他的排名', '标签', '描述']
    # 建立 DataFrame 来储存数据
    data = pd.DataFrame(columns=col)

    # 循环页数
    for i in range(1, n + 1):
        data_temp = pd.DataFrame(
            get_data(base_url, i), columns=col)  # 对应页的数据,临时储存
        data = pd.concat([data, data_temp], axis=0,
                         ignore_index=True)  # 与之前的数据合并在一块
        # 适当的停顿,防止请求过快,封ip
        time.sleep(np.random.rand() * np.random.randint(1, 3))
    return data
base_url = "https://api.bilibili.com/x/web-interface/newlist?callback=jqueryCallback_bili_4431985766884974&rid=33&type=0&pn={}&ps=20&jsonp=jsonp&_=1558156016281"
# 一些的请求头,伪装成浏览器,可以防止一些反爬虫的机制
header = {"Referer": "https://www.bilibili.com/v/anime/serial/?spm_id_from=333.334.b_7072696d6172795f6d656e75.8",
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"}

data = get_all_data(1325)  # 获取1325页的视频数据,页数为网页直接查看获得
filename='bilibili_data.csv'
data.to_csv(filename,encoding="utf-8")

3.数据清洗
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
data = pd.read_csv('C:/Users/3号/PycharmProjects/biliHello/bilibili_data.csv')
data.head()

# 首先查看下数据是否有 nan 值
data.isnull().sum()

查看是哪一行
data[data.isnull()['up主']]
# 去掉这一行
data.drop(26397, inplace=True)
# 再次确认缺失值
data.isnull().sum()
# 查看数据有没有重复项
data.duplicated().sum()
# 确认下最小值
data.min()
# 将上传时间 转换成 datetime 类型
data['上传日期'] = pd.to_datetime(data['上传日期'])
data.drop(data[-1 == data['观看次数']].index, inplace=True)
# 查看一下统计
data.describe()
# 看一下各数据的相关性
data.corr()
# 查看up主投稿的数量
data.groupby("up主").count().sort_values("av号", ascending=False)  # 根据up主投稿的数量排序
data.sort_values("观看次数", ascending=False).reset_index(drop=True)
data.sort_values("收藏", ascending=False).reset_index(drop=True)  # 收藏数量排序
data.sort_values("观看次数", ascending=False).reset_index(drop=True)['观看次数'].plot()
# 查看投币排序
data.sort_values("投币", ascending=False).reset_index(drop=True)['投币'].plot()
# 查看一下根据投稿时间的播放量情况
plt.plot(data.set_index("上传日期")['观看次数'].sort_index())
plt.title(u'播放量', fontproperties=font_hei)
# 得到对应的的番剧信息
data.set_index("上传日期")["2014"].sort_values("观看次数", ascending=False).iloc[0]

 

四、结论(10分)


1.经过对主题数据的分析与可视化,可以得到哪些结论?

    1.观看次数、弹幕、评论、投币和分享之间都有很大的相关性。

     2.收藏的的很多都是剧场版。可能是相对于TV版,剧场版制作更精良的缘故。

     3. 播放次数到10000左右就趋近于持平。播放次数和投币次数的相关性很强,趋势几乎相同。

     4.2014年末开始,播放量剧增。
2.对本次程序设计任务完成的情况做一个简单的小结。

     在这次爬虫的过程中,最大的难点在于B站数据的爬取和破解B站反爬,通过上网查资料学习,终于成功获取了1327页的视频数据。

上一篇:JDBC


下一篇:实现mypwd