【Python爬虫课程设计】无名小站——数据爬取+数据可视化
一、选题背景介绍
在当今数字化的时代,动漫产业作为文化创意产业的重要组成部分,正迅速发展。越来越多的人对动漫作品产生浓厚的兴趣,而动漫相关的数据也成为了研究和分析的重要资源。然而,这些数据通常分散在各个网站和平台上,获取和整合这些数据变得困难且耗时。为了解决这一问题,爬取动漫数据的技术应运而生。通过使用合适的爬虫工具和技术,我们可以从动漫相关的网站上自动化地获取各种数据,如动漫作品的信息、角色介绍、评分、评论等。这些数据可以帮助我们深入了解动漫产业的发展趋势、观众的喜好以及市场的需求。
二、主题式网络爬虫设计方案
- 主题式网络爬虫名称:无名小站动漫爬虫(https://www.btnull.org/ac/ )
- 主题式网络爬虫爬取的内容与数据特征分析:
- 爬取内容:无名小站动漫
- 数据特征分析:动漫热度,名称,评分
- 实现思路:
- 先从网址定位每一个动漫的div再从里面获取同时存储好每一获取的信息,循规进入到每一首古诗的页面,爬取页面信息。分标题,热度,评分三个个部分进行抓取,把抓取到的数据存储到excel文件中,读取excel文件,读取每个动漫的正文,进行数据清洗(对保存前进行逻辑处理),去除停用词等,用分词后的数据绘制词云图,,按热度、评分等进行数据统计,并绘图进行可视化。
- 技术难点:
- 网站反爬虫机制:许多动漫网站会采取反爬虫措施来防止自动化爬虫程序的访问。这些机制可能包括验证码、IP 封锁、请求频率限制等。你需要了解并应对这些反爬虫机制,例如使用合适的请求头、代理服务器、随机延迟等技术来规避限制。
- 数据结构和页面布局的复杂性:动漫网站的页面结构和数据展示方式可能比较复杂,需要使用适当的解析库(如 BeautifulSoup、XPath 等)来提取所需的数据。此外,动漫数据通常以不同的格式(如 HTML、JSON、XML 等)呈现,你需要选择合适的解析方法来处理不同的数据格式。
- 大量数据的处理和存储:爬取动漫数据可能会产生大量的数据,需要有效地处理和存储这些数据。你需要考虑数据的去重、清洗、格式化以及存储到合适的数据结构(如数据库、文件等)中。同时,还需要考虑数据的更新和维护。
三、主题页面的结构特征分析


四、网络爬虫程序设计
- 爬取数据:
![]()
爬取数据及导入excel代码:
import json
import re
import numpy as np
import pandas as pd
import requests
from bs4 import BeautifulSoup
from openpyxl import load_workbook
# 清洗热度参数,把带有万字的参数进行清洗整理成数值类型
def multiply_value(number):
if number:
# 将整数转换为字符串
if isinstance(number, int):
return number
else:
# 将字符串中的数字部分提取出来,并转换为浮点数
number_float = float(number.replace('万', '')) * 10000
return number_float
else:
return 0
# 将数据导入到excel表中
def am_ex(a, t, r, d):
wb = load_workbook(r'example.xlsx') # 获取已存在的工作簿
ws = wb.active # 获取工作表
# 将list写入单元格
# 导入动漫名字
for i, item in enumerate(t):
ws.cell(row=a + i + 1, column=1, value=item)
# 导入动漫热度
# 将列表中的字符串转换为浮点数
for i, item in enumerate(r):
item = multiply_value(item)
ws.cell(row=a + i + 1, column=2, value=item)
# 导入动漫评分
for i, item in enumerate(d):
# 如果参数是N/A 改成0加入到excel表中
if item == 'N/A':
item = 0
ws.cell(row=a + i + 1, column=3, value=item)
# 保存 Excel 文件
wb.save('example.xlsx')
# 请求头
headers = {
# 设置浏览器查看的设备名称
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 '
'Safari/537.36 Edg/115.0.1901.200',
# 从哪个网页跳转的
'Referer': 'https://www.btnull.org/',
# 该网页需要登录才可以访问
'Cookie': 'PHPSESSID=ht819kc7ult6uhe2sn4tql76ev; '
'BT_auth=2ccfOD45gks8PbL9tpXGvwfqCiksaQzCfSGK0TMcBfR7ISTfS7TYIC3iLWDd6SiJfbRm6Ctaj'
'-d0zgyJLVJ1K7KA0iZfzN34bpBkboj595gG3gMovOpifLGMpQ5Hpz5S96RzxF72fPZf-emB4iX50pcWIpH9VnYDLap0x0o; '
'BT_cookietime=796aIRXeQPGo_yaLjgKXbjCGTXAroEFUz-L-v955kpdn7PNqG1Sg'
}
# 保存最大行数
row_max = 0
for i in range(1, 54):
# 获取已存在的工作簿
wb = load_workbook(r'example.xlsx')
# 获取工作表
ws = wb.active
# 最大行数数据不保存在循环内部
row_max = ws.max_row
# 网站地址
url = "https://www.btnull.org/ac/------" + str(i)
# requests 库发送一个 GET 请求到指定的 URL,并将响应结果存储在变量 req 中。
req = requests.get(url, headers=headers)
# 手动设置编码格式
req.encoding = 'utf-8'
# 使用 BeautifulSoup 解析响应
soup = BeautifulSoup(req.text, 'html.parser')
# 在此处使用 BeautifulSoup 对象进行操作
script = soup.select('body > script')
# 获取 <script> 标签下的文本内容
script_content = script[0].text
# 使用正则表达式提取 _obj.inlist 的值
page_value = re.search(r'_obj.inlist=({.*?})', script_content).group(1)
# 将 JSON 字符串转化为 Python 对象
json_object = json.loads(page_value)
# 番剧名字
t = json_object.get("t")
# 热度
r = json_object.get("r")
# 遍历列表,将字符串转换为数字
# 评分
d = json_object.get("d")
# 导入数据进行循环添加
am_ex(row_max, t, r, d)
- 散点图:
根据动漫的热度和评分进行散点图并且使用LinearRegression进行回归曲线的计算

散点图与回归线代码:
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib import font_manager
# 地址
path="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf"
# 设置字体路径
my_font = font_manager.FontProperties(fname=path)
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
# 建立颜色列表
colors = 'red'
# x 和 y 轴的数据
pf = pd.read_excel('example.xlsx',
usecols=[1,2])
# 确定画布
plt.figure(figsize=(16, 10))
# 绘制散点图
plt.scatter(pf['评分'],
pf['热度'],
c = colors,
)
# 设置x轴刻度
plt.xticks([1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'])
# 设置y轴刻度
plt.yticks([ 100000, 150000, 250000, 500000, 1000000],
[ '100k', '150k', '250k', '500k', '1000k'])
# 计算回归线
# 将 pay_money 的值转换为二维数组
X = pf['评分'].values.reshape(-1, 1)
# 将 buy_count 的值转换为二维数组
y = pf['热度'].values.reshape(-1, 1)
# 创建 LinearRegression 模型
reg = LinearRegression()
# 使用数据进行拟合
reg.fit(X,y)
# 使用拟合得到的模型 reg 对 X 进行预测,并且设置线条颜色
plt.plot(X, reg.predict(X), color='green')
# 添加标题
plt.title('动漫评分和热度散点图')
# 添加x名字
plt.xlabel('评分')
# 添加y名称
plt.ylabel('热度')
# 显示图形
plt.show()
- 饼图:
读取动漫评分统计各类评分的数量,进行4个分类分别为评分小于4与没评分,评分大于等于6小于8,大于8的评分,评分大于等于4小于6,在进行百分比的计算

饼图代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager
# 打开 Excel 文件,需要将 example.xlsx 替换为正确的路径
pf = pd.read_excel('example.xlsx', usecols=[2])
# 地址
path="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf"
# 设置字体路径
my_font = font_manager.FontProperties(fname=path)
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
# 每一块的颜色
colors = ['yellowgreen', 'gold', 'lightskyblue', 'lightcoral']
# 统计评分
# 小于4或无值
n = 0
# 大于8
e = 0
# 大于等于6小于8
s = 0
# 大于等于4小于6
f = 0
# 循环遍历统计各评分数量
for i in pf.values:
# 评分小于4与没评分
if np.isnan(i) or i[0] < 4:
n = n + 1
# 大于8的评分
elif i[0] >= 8:
e = e + 1
# 评分大于等于6小于8
elif 8 > i[0] >= 6:
s = s + 1
# 评分大于等于4小于6
elif 6 > i[0] >= 4:
f = f + 1
# 总数
print(n,e,s,f)
sum = n + e + s + f
# 定义饼图的标签
labels = ['大于8的评分', '评分大于等于6小于8', '评分小于4与没评分', '评分大于等于4小于6']
# 定义饼图的百分比参数
percentages = [sum/e, sum/s, sum/n, sum/f]
# 绘制饼图
plt.pie(percentages, labels=labels, autopct='%1.1f%%',colors=colors)
# 添加标题
plt.title('动漫评分统计饼图')
# 显示图形
plt.show()
- 词云图:
读取excel表中的动漫名称进行拼接处理,设置禁止词及最大生成数量生成词云图

词云图代码:
import jieba
import pandas as pd
from wordcloud import WordCloud, wordcloud
# 词云参数
# 字体地址
font_path = "Arial Unicode.ttf"
# 生成图片宽度
width = 500
# 生成图片高度
height = 700
# 生成图片背景颜色
background_color = 'white'
max_words = 500
# 读取 Excel 文件
pf = pd.read_excel('example.xlsx', usecols=[0])
# 保存表格内容
list = []
# 遍历表格内容,将每行数据添加到列表中
for item in pf.values:
list.append(item[0])
r_data = ''.join(list)
# 将列表转换为字符串
data = list
# 连接成字符串
str_list = ''.join(list)
# 生成分词列表
ls = jieba.lcut(r_data)
# 连接成字符串
text = ' '.join(ls)
# 设置停止词
stopwords = ["第二季", "第一季", "第三季", "第四季", "的", "我", "是", "与", "了", "世界", "之", "你", "在", "不"]
# 创建词云对象
wc = wordcloud.WordCloud(font_path=font_path,
width=width,
height=height,
background_color=background_color,
max_words=max_words,
stopwords=stopwords)
# 生成词云
wc.generate(text)
# 保存词云文件
wc.to_file("wordcloud.png")
- 直方图:
取excel中热度,动漫名称,把热度进行排序取前10个最大热度的动漫标题和热度进行绘制直方图和折线图

直方图代码:
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib import font_manager
from pylab import mpl
import seaborn as sns
# 查找数据中前n个最大的值
def get_top_n_values(lst, n):
# 如果列表长度小于 n,直接返回列表
if len(lst) < n:
return lst
# 将列表按降序排序,找到最大的 n 个值
sorted_lst = sorted(lst, reverse=True)
# 返回前 n 个最大值
return sorted_lst[:n]
# 设置字体路径
my_font = font_manager.FontProperties(fname="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf")
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
# 读取 Excel 文件
df = pd.read_excel('example.xlsx')
# 提取动漫名称、热度和评分列
name = df['动漫名称']
heat = df['热度']
pf = pd.read_excel('example.xlsx', usecols=[0, 1])
# 使用 sorted 函数根据热度值降序排序
sorted_data = sorted(pf.values, key=lambda x: x[1], reverse=True)
list_title = []
list_rd = []
# 前 10 个热度值
for i in range(0, 10):
list_title.append(sorted_data[:10][i][0])
list_rd.append(sorted_data[:10][i][1])
# 创建图表
plt.figure(figsize=(15, 6))
plt.bar(list_title, list_rd, color='r')
plt.xlabel('动漫名称')
# 设置y轴刻度
plt.yticks([500000, 1000000, 1250000, 1500000, 2000000],
['500k', '1000k', '1250k', '1500k', '2000k'])
plt.ylabel('热度')
plt.title('动漫热度前十直方图')
# 添加评分的折线图
plt.plot(list_title, list_rd, color='b', linestyle='--')
# 显示图形
plt.show()
五、总结
- 使用request对无名小站的动漫区进行分析html爬取热度,标题,评分的数据
- 对爬取的数据进行数据的清洗过滤和整合
- 对评分进行划分区间做饼图,对热度进行排序取前10个最大热度做直方图和折线图,对动漫标题做拼接做词云图,对评分和热度进行关联做散点图并加入预测回归线
- 通过 Python 爬虫和可视化技术,我们可以从动漫网站上抓取相关数据,并将其以直观的方式展示出来,以便更好地理解和分析动漫市场的趋势和规律。在进行这个项目时,需要注意合法合规的问题,并根据具体需求选择合适的技术和工具
- 在本次项目中是根据自己的兴趣爱好选取的网站,本次学习到了很多自己之前不会的技术如:可视化,爬虫,中文乱码,导入excel表的3种方式,在学习中也遇到了很多bug和问题,在这次学习让我更好的知道了pyhon这个语言的强大之处,之后会更加努力的去学习
import json
import re
import numpy as np
import pandas as pd
import requests
from bs4 import BeautifulSoup
from openpyxl import load_workbook
# 清洗热度参数,把带有万字的参数进行清洗整理成数值类型
def multiply_value(number):
if number:
# 将整数转换为字符串
if isinstance(number, int):
return number
else:
# 将字符串中的数字部分提取出来,并转换为浮点数
number_float = float(number.replace('万', '')) * 10000
return number_float
else:
return 0
# 将数据导入到excel表中
def am_ex(a, t, r, d):
wb = load_workbook(r'example.xlsx') # 获取已存在的工作簿
ws = wb.active # 获取工作表
# 将list写入单元格
# 导入动漫名字
for i, item in enumerate(t):
ws.cell(row=a + i + 1, column=1, value=item)
# 导入动漫热度
# 将列表中的字符串转换为浮点数
for i, item in enumerate(r):
item = multiply_value(item)
ws.cell(row=a + i + 1, column=2, value=item)
# 导入动漫评分
for i, item in enumerate(d):
# 如果参数是N/A 改成0加入到excel表中
if item == 'N/A':
item = 0
ws.cell(row=a + i + 1, column=3, value=item)
# 保存 Excel 文件
wb.save('example.xlsx')
# 请求头
headers = {
# 设置浏览器查看的设备名称
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 '
'Safari/537.36 Edg/115.0.1901.200',
# 从哪个网页跳转的
'Referer': 'https://www.btnull.org/',
# 该网页需要登录才可以访问
'Cookie': 'PHPSESSID=ht819kc7ult6uhe2sn4tql76ev; '
'BT_auth=2ccfOD45gks8PbL9tpXGvwfqCiksaQzCfSGK0TMcBfR7ISTfS7TYIC3iLWDd6SiJfbRm6Ctaj'
'-d0zgyJLVJ1K7KA0iZfzN34bpBkboj595gG3gMovOpifLGMpQ5Hpz5S96RzxF72fPZf-emB4iX50pcWIpH9VnYDLap0x0o; '
'BT_cookietime=796aIRXeQPGo_yaLjgKXbjCGTXAroEFUz-L-v955kpdn7PNqG1Sg'
}
# 保存最大行数
row_max = 0
for i in range(1, 54):
# 获取已存在的工作簿
wb = load_workbook(r'example.xlsx')
# 获取工作表
ws = wb.active
# 最大行数数据不保存在循环内部
row_max = ws.max_row
# 网站地址
url = "https://www.btnull.org/ac/------" + str(i)
# requests 库发送一个 GET 请求到指定的 URL,并将响应结果存储在变量 req 中。
req = requests.get(url, headers=headers)
# 手动设置编码格式
req.encoding = 'utf-8'
# 使用 BeautifulSoup 解析响应
soup = BeautifulSoup(req.text, 'html.parser')
# 在此处使用 BeautifulSoup 对象进行操作
script = soup.select('body > script')
# 获取 <script> 标签下的文本内容
script_content = script[0].text
# 使用正则表达式提取 _obj.inlist 的值
page_value = re.search(r'_obj.inlist=({.*?})', script_content).group(1)
# 将 JSON 字符串转化为 Python 对象
json_object = json.loads(page_value)
# 番剧名字
t = json_object.get("t")
# 热度
r = json_object.get("r")
# 遍历列表,将字符串转换为数字
# 评分
d = json_object.get("d")
# 导入数据进行循环添加
am_ex(row_max, t, r, d)
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib import font_manager
from pylab import mpl
import seaborn as sns
# 查找数据中前n个最大的值
def get_top_n_values(lst, n):
# 如果列表长度小于 n,直接返回列表
if len(lst) < n:
return lst
# 将列表按降序排序,找到最大的 n 个值
sorted_lst = sorted(lst, reverse=True)
# 返回前 n 个最大值
return sorted_lst[:n]
# 设置字体路径
my_font = font_manager.FontProperties(fname="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf")
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
# 读取 Excel 文件
df = pd.read_excel('example.xlsx')
# 提取动漫名称、热度和评分列
name = df['动漫名称']
heat = df['热度']
pf = pd.read_excel('example.xlsx', usecols=[0, 1])
# 使用 sorted 函数根据热度值降序排序
sorted_data = sorted(pf.values, key=lambda x: x[1], reverse=True)
list_title = []
list_rd = []
# 前 10 个热度值
for i in range(0, 10):
list_title.append(sorted_data[:10][i][0])
list_rd.append(sorted_data[:10][i][1])
# 创建图表
plt.figure(figsize=(15, 6))
plt.bar(list_title, list_rd, color='r')
plt.xlabel('动漫名称')
# 设置y轴刻度
plt.yticks([500000, 1000000, 1250000, 1500000, 2000000],
['500k', '1000k', '1250k', '1500k', '2000k'])
plt.ylabel('热度')
plt.title('动漫热度前十直方图')
# 添加评分的折线图
plt.plot(list_title, list_rd, color='b', linestyle='--')
# 显示图形
plt.show()
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager
# 打开 Excel 文件,需要将 example.xlsx 替换为正确的路径
pf = pd.read_excel('example.xlsx', usecols=[2])
# 地址
path="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf"
# 设置字体路径
my_font = font_manager.FontProperties(fname=path)
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
# 每一块的颜色
colors = ['yellowgreen', 'gold', 'lightskyblue', 'lightcoral']
# 统计评分
# 小于4或无值
n = 0
# 大于8
e = 0
# 大于等于6小于8
s = 0
# 大于等于4小于6
f = 0
# 循环遍历统计各评分数量
for i in pf.values:
# 评分小于4与没评分
if np.isnan(i) or i[0] < 4:
n = n + 1
# 大于8的评分
elif i[0] >= 8:
e = e + 1
# 评分大于等于6小于8
elif 8 > i[0] >= 6:
s = s + 1
# 评分大于等于4小于6
elif 6 > i[0] >= 4:
f = f + 1
# 总数
print(n,e,s,f)
sum = n + e + s + f
# 定义饼图的标签
labels = ['大于8的评分', '评分大于等于6小于8', '评分小于4与没评分', '评分大于等于4小于6']
# 定义饼图的百分比参数
percentages = [sum/e, sum/s, sum/n, sum/f]
# 绘制饼图
plt.pie(percentages, labels=labels, autopct='%1.1f%%',colors=colors)
# 添加标题
plt.title('动漫评分统计饼图')
# 显示图形
plt.show()
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager
# 打开 Excel 文件,需要将 example.xlsx 替换为正确的路径
pf = pd.read_excel('example.xlsx', usecols=[2])
# 地址
path="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf"
# 设置字体路径
my_font = font_manager.FontProperties(fname=path)
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
# 每一块的颜色
colors = ['yellowgreen', 'gold', 'lightskyblue', 'lightcoral']
# 统计评分
# 小于4或无值
n = 0
# 大于8
e = 0
# 大于等于6小于8
s = 0
# 大于等于4小于6
f = 0
# 循环遍历统计各评分数量
for i in pf.values:
# 评分小于4与没评分
if np.isnan(i) or i[0] < 4:
n = n + 1
# 大于8的评分
elif i[0] >= 8:
e = e + 1
# 评分大于等于6小于8
elif 8 > i[0] >= 6:
s = s + 1
# 评分大于等于4小于6
elif 6 > i[0] >= 4:
f = f + 1
# 总数
print(n,e,s,f)
sum = n + e + s + f
# 定义饼图的标签
labels = ['大于8的评分', '评分大于等于6小于8', '评分小于4与没评分', '评分大于等于4小于6']
# 定义饼图的百分比参数
percentages = [sum/e, sum/s, sum/n, sum/f]
# 绘制饼图
plt.pie(percentages, labels=labels, autopct='%1.1f%%',colors=colors)
# 添加标题
plt.title('动漫评分统计饼图')
# 显示图形
plt.show()
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib import font_manager
# 地址
path="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf"
# 设置字体路径
my_font = font_manager.FontProperties(fname=path)
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
# 建立颜色列表
colors = 'red'
# x 和 y 轴的数据
pf = pd.read_excel('example.xlsx',
usecols=[1,2])
# 确定画布
plt.figure(figsize=(16, 10))
# 绘制散点图
plt.scatter(pf['评分'],
pf['热度'],
c = colors,
)
# 设置x轴刻度
plt.xticks([1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'])
# 设置y轴刻度
plt.yticks([ 100000, 150000, 250000, 500000, 1000000],
[ '100k', '150k', '250k', '500k', '1000k'])
# 计算回归线
# 将 pay_money 的值转换为二维数组
X = pf['评分'].values.reshape(-1, 1)
# 将 buy_count 的值转换为二维数组
y = pf['热度'].values.reshape(-1, 1)
# 创建 LinearRegression 模型
reg = LinearRegression()
# 使用数据进行拟合
reg.fit(X,y)
# 使用拟合得到的模型 reg 对 X 进行预测,并且设置线条颜色
plt.plot(X, reg.predict(X), color='green')
# 添加标题
plt.title('动漫评分和热度散点图')
# 添加x名字
plt.xlabel('评分')
# 添加y名称
plt.ylabel('热度')
# 显示图形
plt.show()

浙公网安备 33010602011771号