1. 需求分析
1.1 网络爬虫需求
抓取CSDN博客发布所有的数据,并将数据写入Excel文件,并将所有博客名称写入文本文件。
抓取CSDN博客2021年各月发布博客的数据,并分别将每月的数据写入Excel文件。统计每月发布博客的数量,统计每月的总阅读量,并将统计结果保存到Excel文件。
通过对爬取网页的html分析,爬取网页的数据,将爬取的数据保存到文件,用于对数据进行可视化。
图 1 爬取博客数据流图
1.2 数据可视化需求
将统计的数据进行可视化,使爬取网站的数据用更直观的效果展示,当数据获取完成,我们使用相关模块对数据进行清洗处理,并对数据做可视化分析,并理解每一个图标所代表意义。
图 2 可视化数据流图
2. 总体设计
2.1 网页分析
https://blog.csdn.net/gezongbo/article/list/1
https://blog.csdn.net/gezongbo/article/list/2
https://blog.csdn.net/gezongbo/article/list/3
https://blog.csdn.net/gezongbo/article/list/4
可以发现要爬取的网址的规律。
图 3 爬取博客数据网页
图 4 网页具体内容
通过使用正则表达式匹配字符串,获取想要的数据。
https://blog.csdn.net/gezongbo/article/month/2021/11
https://blog.csdn.net/gezongbo/article/month/2021/10
https://blog.csdn.net/gezongbo/article/month/2021/09
…
可以发现要爬取的网址的规律。
图 5 按照月份爬取博客网页
2.2 数据可视化设计
将爬取的数据用多种图表的显示。例如:条形图,饼图,散点图,词云等形式。利用python的pandas模块将数据文件读入。导入matplotlib, pyecharts等模块,调用模块画图的相应函数。进行数据可视化,并将可视化结果保存为图片。
图 6 可视化程序流程图
3 系统实现
3.1 网页抓取
3.1.1 设置headers
先在浏览器打开要爬取的网页,获取User-Agent和Cookie
按F12,点击网络查看User-Agent和Cookie
图 7 查看User-Agent和Cookie
headers = {
'Referer': 'https://blog.csdn.net/gezongbo',
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36",
"Cookie" : 'id=22c631daf5cb00b9||t=1632837730|et=730|cs=002213fd48870e779530817cb9; expires=Thu, 28-Sep-2023 14:02:10 GMT; path=/; domain=.doubleclick.net; Secure; HttpOnly; SameSite=none'
}
3.1.2 抓取网页
web = requests.get(url, timeout=30, headers=headers)
web.encoding = web.apparent_encoding
if web.status_code == 200:
return web.text
3.2 数据识别
3.2.1 使用正则表达式
bokelist = [['博客ID', '博客链接', '是否原创', '博客名称', '博客内容', '发布时间', '阅读量']]
#print(html)
pattern = re.compile(
'<div class="article-item-box csdn-tracking-statistics" data-articleid="(.*?)">.*?'#博客ID
'<h4 class="">.*?<a href="(.*?)".*?'#博客链接
'<span class="article-type type-1 float-none">(.*?)</span>(.*?)</a>.*?</h4>.*?'#是否原创,博客名称
'<p class="content">(.*?)</p>.*?'#文章内容
'<div class="info-box d-flex align-content-center">.*?<span class="date">(.*?)</span>.*?'#发布时间
'alt="">(.*?)</span>.*?</div>'#阅读量
, re.S)
items = re.findall(pattern, str(html))
print(items)
3.2.2 统计数据
#统计每月发布博客数量和总阅读量
totallist = [['月份', '博客数量', '总阅读量']]
def totalData(bokelist,mouth):
boke_count=0
read_num_count=0
for item in bokelist[1:]:
#print(item[3])
boke_count +=1
#print(item[6])
read_num_count +=int(item[6])
totallist.append([mouth,boke_count,read_num_count])
print(totallist)
return totallist
3.3 数据存储
3.3.1 写入文本文件
def write_to_txt(bokelist):
with open('./data/博客名称.txt', 'a', encoding='utf-8') as f:
for item in bokelist:
f.write(item[3]+ ',')
3.3.2 写入Excel文件
wb = xw.Book('./data/gezongbo博客数据.xlsx')
sht = wb.sheets('Sheet1')
sht.range('a1').value = info # 将数据添加到表格中
3.4 数据可视化
3.4.1 散点图
'''博客阅读量散点分布'''
def sandian():
# 读取数据
df = pd.read_excel("./data/统计2021年各月份博客数据.xlsx", engine='openpyxl')
read_num = list(df["总阅读量"])
date = list(df["月份"])
plt.figure(figsize=(9, 6), dpi=100)
# 绘制散点图 设置点的颜色
plt.scatter(date, read_num, c='r')
# 添加描述信息 设置字体大小
plt.xlabel("月份", fontsize=12)
plt.ylabel("总阅读量", fontsize=12)
plt.title("博客阅读量散点分布", fontsize=15)
# 添加网格 网格的透明度 线条样式
plt.grid(alpha=0.5, linestyle=":")
plt.savefig('./data/散点图.png')
plt.show()
3.4.2 条形图
def taioxing():
df = pd.read_excel("./data/统计2021年各月份博客数据.xlsx", engine='openpyxl')
# 设置绘图风格
plt.style.use('ggplot')
# 绘制条形图
plt.bar(x=range(df.shape[0]), # 指定条形图x轴的刻度值
height=df["博客数量"], # 指定条形图y轴的数值
tick_label=df["月份"], # 指定条形图x轴的刻度标签
color='steelblue', # 指定条形图的填充色
)
# 添加x轴的标签
plt.xlabel('月份')
# 添加y轴的标签
plt.ylabel('总阅读量')
# 添加条形图的标题
plt.title('2021年gezongbo博客发布情况')
# 显示图形
plt.savefig('./data/条形图.png')
plt.show()
3.4.3 饼图
'''2021年各月阅读量饼图可视化'''
def bingtu():
# 读取数据
df = pd.read_excel("./data/统计2021年各月份博客数据.xlsx", engine='openpyxl')
read_num = df['总阅读量']
mouth = ['1月', '3月', '5月', '8月', '9月','10月','11月']
explode = [0, 0.05, 0, 0, 0, 0, 0] # 生成数据,用于突出显示3月
colors = ['#9999ff', '#ff9999', '#7777aa', '#2442aa', '#dd5555', '#ff9999', '#2442aa'] # 自定义颜色
# 将横、纵坐标轴标准化处理,确保饼图是一个正圆,否则为椭圆
plt.axes(aspect='equal')
# 绘制饼图
plt.pie(x=read_num, # 绘图数据
explode=explode, # 突出显示3月份
labels=mouth, # 添加月份标签
colors=colors, # 设置饼图的自定义填充色
autopct='%.1f%%', # 设置百分比的格式,这里保留一位小数
pctdistance=0.8, # 设置百分比标签与圆心的距离
labeldistance=1.1, # 设置月份标签与圆心的距离
startangle=180, # 设置饼图的初始角度
radius=1.2, # 设置饼图的半径
counterclock=False, # 是否逆时针,这里设置为顺时针方向
wedgeprops={'linewidth': 1.5, 'edgecolor': 'green'}, # 设置饼图内外边界的属性值
textprops={'fontsize': 10, 'color': 'black'}, # 设置文本标签的属性值
)
# 添加图标题
plt.title('各月阅读量')
# 显示图形
plt.savefig('./data/饼图.png')
plt.show()
3.4.4 词云
def ciyun():
# r''单引号里面不需要转义
font = r'C:\Windows\Fonts\simkai.ttf' # 电脑自带的字体
def tcg(texts):
cut = jieba.cut(texts) # 分词
string = ' '.join(cut)
return string
text = (open('./data/博客名称.txt', 'r', encoding='utf-8')).read()
string = tcg(text)
img = Image.open('./data/background.jpg') # 打开图片
img_array = np.array(img) # 将图片装换为数组
stopword = [''] # 设置停止词,也就是你不想显示的词
wc = WordCloud(
background_color='white',
width=1000,
height=800,
mask=img_array, # 设置背景图片
font_path=font,
stopwords=stopword
)
wc.generate_from_text(string) # 绘制图片
plt.imshow(wc)
plt.axis('off')
plt.show() # 显示图片
wc.to_file('./data/词云.png') # 保存图片
4 结论
图 8 博客阅读量散点分布
图 9 博客发布情况
图 10 各月阅读量占比
图 11 博客名称词云可视化