【python爬虫课程设计】类型数据爬取+数据可视化
选题的背景
稀土掘金作为国内最大的开发者社区,汇集了大量优质的技术文章和资源。通过爬取稀土掘金数据,可以深入了解当前技术领域的热点、趋势以及开发者的需求,为相关企业和机构提供有价值的参考信息。预期目标是分析热门技术主题、作者影响力、文章质量等方面,为企业决策、技术研发和人才培养提供数据支持。
主题式网络爬虫设计方案
- 主题式网络爬虫名称:稀土掘金主题爬虫
- 主题式网络爬虫爬取的内容与数据特征分析:
- 爬取内容:课程掘金小册
- 数据特征分析:所有小册、价钱、标签类型
- 实现思路:
- 导入所需的库,包括json、requests和csv。
- 设置请求头headers,包括User-Agent和Referer。
- 定义CSV文件名result_csv和数据列表data_list。
- 使用with语句打开CSV文件,并创建一个csv.writer对象。
- 使用for循环每次执行以下操作:构造请求体data。使用requests库发送POST请求,获取响应结果。解析响应结果,提取所需数据。
- 技术难点:
- 网站可能采用Ajax技术加载内容,需要分析请求过程,模拟登录和获取动态内容。
- 网站可能会采取一定的反爬措施,如验证码、IP封禁等,需要设计相应的应对策略。
主题页面的结构特征分析
主题页面的结构与特征分析
- 顶部导航栏
- 类型导航位于中间的导航栏
- 下面是所有小册
- 不断往下滑,加载新的小册
Htmls 页面解析
<div class="phone-show-menu isResourceVisible" data-V-925171a8>
顶部导航栏<div class="cates-label-wrap” data-v-0f9eb81c data-v-4b6aa530 data-v-7bb7d93a data-v-ffd280d8></div>
类型导航<span data-v-0c863bb9 data-v-f2a3effo title="CSS 工程化核心原理与实战”class="text-highlight” data-v-65b50b51>CSS 工程化核心原理与实战</span>
小册
节点(标签)查找方法与遍历方法
遍历方法for 循环:for i in range(0, 9): # 循环获取数据:9 次 =》 160 的量
网络爬虫程序设计
爬取数据
爬取 小册名、原价钱、类型、阅读人数 的网页数据并保存到 result.csv 文件中
import json
import requests
import csv
aid = 2608
uuid = 7308550062022411803
spider = 0
# 网站地址
url = "https://api.juejin.cn/booklet_api/v1/booklet/listbycategory?aid=" + str(aid) + "&uuid=" + str(uuid) + "&spider=" + str(spider)
# 请求头
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://juejin.cn/'
}
# csv文件
result_csv = 'res.csv'
# category 类型 | title 书名 | pay_money 折扣后价钱 | buy_count 阅读/购买人数
data_list = ["category", "title", "pay_money", "buy_count"]
# 循环,先添加字段名
with open(result_csv, 'a+', encoding='gbk', newline='') as ff:
writer = csv.writer(ff)
writer.writerow(data_list)
# 循环获取数据:9 次 =》 160 的量
cursor = 0
category = ''
for i in range(0, 9):
# 请求体
data = {
'category_id': "0",
'cursor': str(cursor),
'is_vip': 0,
'limit': 20,
'sort': 7
}
# 获取每页的数据量
cursor += 20
# requests 库发送一个 GET 请求到指定的 URL,并将响应结果存储在变量 req 中。
req = requests.post(url, headers=headers, data=data)
# 手动设置编码格式
req.encoding = 'utf-8'
a = req.text
# 将 JSON 字符串转化为 Python 对象
json_object = json.loads(a)
# 通过键名获取对应的值
b = json_object.get("data")
# 类型id 对应的 类型名称
cate_arr = [
["6809637769959178254", "6809637767543259144", "6809635626879549454",
"6809635626661445640", "6809637773935378440", "6809637771511070734",
"6809637776263217160", "6809637772874219534"],
["后端", "前端", "Android", "iOS", "人工智能", "开发工具", "代码人生", "阅读"]
]
# 遍历解析后的数据
for item in b:
# 创建列表
res_list = []
# 打印 对比结果
# print(item['base_info'])
# print(item['max_discount'])
# 提取解析数据中的 base_info 字典数据
a = item['base_info']
# 提取解析数据中的 max_discount 字典数据
b = item['max_discount']
# 打印 对比结果
# print("类型:" + a['category_id'])
# print("书名:" + a['title'])
# print("阅读人数:" + str(a['buy_count']))
# print("折扣后价钱:" + str(b['pay_money'] / 100))
# category 类型 | title 书名 | pay_money 折扣后价钱 | buy_count 阅读/购买人数
# category = a['category_id']
title = a['title']
pay_money = b['pay_money'] / 100
buy_count = a['buy_count']
# 将 ar['category_id'] 与 cate_arr 列表中的第一维列表进行判断
for catei in cate_arr[0]:
# 在匹配时,取出 cate_arr 列表中的第二维列表的值
if catei == a['category_id']:
# print(a['category_id'])
# 打印,取出 cate_arr 列表中的第二维列表的值
# print("类型:" + str(cate_arr[1][cate_arr[0].index(catei)]))
category = str(cate_arr[1][cate_arr[0].index(catei)])
# 追加数据,【输出 category 字段】
res_list.append(category)
break
# 追加数据,【输出 title 字段】
res_list.append(title)
# 追加数据,【输出 pay_money 字段】
res_list.append(pay_money)
# 追加数据,【输出 buy_count 字段】
res_list.append(buy_count)
# 在一个已存在的 CSV 文件 result_csv 的末尾添加一行数据 res_list
with open(result_csv, 'a+', encoding='gbk', newline='') as f:
writer = csv.writer(f)
writer.writerow(res_list)
散点图
根据 res.csv 文件中的 阅读人数和价格,画出散点图并且计算出回归线
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.linear_model import LinearRegression
### 散点图、回归线:阅读人数、价格
def plot_reading_numbers(data):
# 提取价钱数据
pay_money = data['pay_money']
# 提取阅读人数数据
buy_count = data['buy_count']
# 打印 价钱和阅读人数
# print(pay_money)
# print(buy_count)
# 绘制散点图 (x, y)
plt.scatter(pay_money, buy_count)
# 设置 X横轴区间
plt.xlim(0, 36)
# 设置 Y横轴刻值
plt.xticks([0, 5, 10, 15, 20, 25, 30, 36])
# 设置 X横轴区间
plt.ylim(0, 7000)
# 设置 Y横轴刻值
plt.yticks([0, 1000, 2000, 3000, 4000, 5000, 6000, 7000])
# 计算回归线
# 将 pay_money 的值转换为二维数组
X = pay_money.values.reshape(-1, 1)
# 将 buy_count 的值转换为二维数组
y = buy_count.values.reshape(-1, 1)
# 创建回归线
reg = LinearRegression().fit(X, y)
# 使用拟合得到的模型 reg 对 X 进行预测,并且设置线条颜色
plt.plot(X, reg.predict(X), color='green')
# 设置 X轴注解
plt.xlabel('阅读人数')
# 设置 Y轴注解
plt.ylabel('价格')
# 设置 标题
plt.title('散点图 和 回归线')
# 将图片保存为 sd.png
plt.savefig('sd.png')
# 实时显示图片
plt.show()
if __name__ == "__main__":
# 中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
# 读取 CSV 文件
data = pd.read_csv('res.csv', encoding='gbk')
# 打印,对比结果
# print(data)
plot_reading_numbers(data)
饼图
根据 res.csv 文件中的 类型、购买人数 做出不同类型下的购买人数进行统计比例,使用饼图显示
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
import numpy as np
### 饼图:类型、购买人数
def plot_reading_numbers(data):
# 删除重复值(数据清洗)
data = data.drop_duplicates()
# print(data)
# 将清洗后的数据添加到 category_list 列表中
category_list = []
for item in data['category'].value_counts().index:
category_list.append(item)
# print(category_list)
# 设置比例图的每一块的颜色
colors = ['yellowgreen', 'gold', 'lightskyblue', 'lightcoral']
# print(data['category'].value_counts().values)
# 使用 matplotlib 库中的 plt.pie() 函数来绘制饼图
plt.pie(data['category'].value_counts().values, labels=category_list, autopct='%1.1f%%', startangle=90)
# 显示为圆(避免比例压缩为椭圆)
plt.axis('equal')
# 设置字体、并且支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']
# 保存饼图
plt.title('不同类型的购买人数的统计比例')
# 将图片保存为 bin.jpg
plt.savefig('bin.jpg')
# 实时显示图片
plt.show()
if __name__ == "__main__":
# 中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
# 读取 CSV 文件
data = pd.read_csv('res.csv', encoding='gbk')
# 打印,对比结果
# print(data)
plot_reading_numbers(data)
直方图
根据 res.csv 文件中的 类型、每本小册的价格 做一个平均价格,并且画出同类型下平均价钱的直方图
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
import numpy as np
### 直方图:类型、平均价格
def plot_reading_numbers(data):
# 对数据进行分组并计算平均价格
grouped_data = data.groupby('category')['pay_money'].mean()
# 绘制直方图
plt.bar(grouped_data.index, grouped_data.values)
# 设置 X 轴注解
plt.xlabel('类型')
# 设置 Y 轴注解
plt.ylabel('平均价格')
# 设置 标题
plt.title('同类型下平均价钱')
# 将图片保存为 zf.jpg
plt.savefig('zf.jpg')
# 实时显示图片
plt.show()
if __name__ == "__main__":
# 中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
# 读取 CSV 文件
data = pd.read_csv('res.csv', encoding='gbk')
# 打印,对比结果
# print(data)
plot_reading_numbers(data)
词云图
根据 res.csv 文件中的 小册名 计算生成热门和推荐的词云图
import pandas as pd
from wordcloud import WordCloud
import matplotlib.pyplot as plt
### 词云图:类型
def plot_reading_numbers(data):
# 提取title字段的数据
titles = ' '.join(data['title'])
# 设置字体文件的路径
font_path = 'simhei.ttf'
# 设置词云图的背景颜色
background_color = 'white'
# 设置词云图的宽度
width = 800
# 设置词云图的高度
height = 800
# 使用 generate() 方法生成词云图
wordcloud = WordCloud(font_path=font_path,
background_color=background_color,
width=width,
height=height).generate(titles)
# 使用imshow()方法显示词云图,并设置插值方式为双线性插值
plt.imshow(wordcloud, interpolation='bilinear')
# 关闭坐标轴
plt.axis('off')
# 将图片保存为 zf.jpg
plt.savefig('cy.jpg')
# 实时显示图片
plt.show()
if __name__ == "__main__":
# 中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
# 读取 CSV 文件
data = pd.read_csv('res.csv', encoding='gbk')
# 打印,对比结果
# print(data)
plot_reading_numbers(data)
总结
- 我使用了阅读人数和价格这两个变量来绘制散点图,从散点图中可以看出,阅读人数和价格之间存在一定的关系。
- 我使用了类型和购买人数这两个变量来绘制饼图,通过观察饼图,直观地了解到各种类型的购买人数在总购买人数中的占比情况。
- 我使用了类型和平均价格这两个变量来绘制直方图,通过观察直方图,了解不同类型的平均价格分布情况,以及各类型在整体中的占比。
- 我使用了类型这个变量来生成词云图,通过观察词云图,直观地了解到不同类型的词汇在整体中的分布情况。
总代码量
import json
import requests
import csv
aid = 2608
uuid = 7308550062022411803
spider = 0
# 网站地址
url = "https://api.juejin.cn/booklet_api/v1/booklet/listbycategory?aid=" + str(aid) + "&uuid=" + str(uuid) + "&spider=" + str(spider)
# 请求头
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://juejin.cn/'
}
# csv文件
result_csv = 'res.csv'
# category 类型 | title 书名 | pay_money 折扣后价钱 | buy_count 阅读/购买人数
data_list = ["category", "title", "pay_money", "buy_count"]
# 循环,先添加字段名
with open(result_csv, 'a+', encoding='gbk', newline='') as ff:
writer = csv.writer(ff)
writer.writerow(data_list)
# 循环获取数据:9 次 =》 160 的量
cursor = 0
category = ''
for i in range(0, 9):
# 请求体
data = {
'category_id': "0",
'cursor': str(cursor),
'is_vip': 0,
'limit': 20,
'sort': 7
}
# 获取每页的数据量
cursor += 20
# requests 库发送一个 GET 请求到指定的 URL,并将响应结果存储在变量 req 中。
req = requests.post(url, headers=headers, data=data)
# 手动设置编码格式
req.encoding = 'utf-8'
a = req.text
# 将 JSON 字符串转化为 Python 对象
json_object = json.loads(a)
# 通过键名获取对应的值
b = json_object.get("data")
# 类型id 对应的 类型名称
cate_arr = [
["6809637769959178254", "6809637767543259144", "6809635626879549454",
"6809635626661445640", "6809637773935378440", "6809637771511070734",
"6809637776263217160", "6809637772874219534"],
["后端", "前端", "Android", "iOS", "人工智能", "开发工具", "代码人生", "阅读"]
]
# 遍历解析后的数据
for item in b:
# 创建列表
res_list = []
# 打印 对比结果
# print(item['base_info'])
# print(item['max_discount'])
# 提取解析数据中的 base_info 字典数据
a = item['base_info']
# 提取解析数据中的 max_discount 字典数据
b = item['max_discount']
# 打印 对比结果
# print("类型:" + a['category_id'])
# print("书名:" + a['title'])
# print("阅读人数:" + str(a['buy_count']))
# print("折扣后价钱:" + str(b['pay_money'] / 100))
# category 类型 | title 书名 | pay_money 折扣后价钱 | buy_count 阅读/购买人数
# category = a['category_id']
title = a['title']
pay_money = b['pay_money'] / 100
buy_count = a['buy_count']
# 将 ar['category_id'] 与 cate_arr 列表中的第一维列表进行判断
for catei in cate_arr[0]:
# 在匹配时,取出 cate_arr 列表中的第二维列表的值
if catei == a['category_id']:
# print(a['category_id'])
# 打印,取出 cate_arr 列表中的第二维列表的值
# print("类型:" + str(cate_arr[1][cate_arr[0].index(catei)]))
category = str(cate_arr[1][cate_arr[0].index(catei)])
# 追加数据,【输出 category 字段】
res_list.append(category)
break
# 追加数据,【输出 title 字段】
res_list.append(title)
# 追加数据,【输出 pay_money 字段】
res_list.append(pay_money)
# 追加数据,【输出 buy_count 字段】
res_list.append(buy_count)
# 在一个已存在的 CSV 文件 result_csv 的末尾添加一行数据 res_list
with open(result_csv, 'a+', encoding='gbk', newline='') as f:
writer = csv.writer(f)
writer.writerow(res_list)
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.linear_model import LinearRegression
### 散点图、回归线:阅读人数、价格
def plot_reading_numbers(data):
# 提取价钱数据
pay_money = data['pay_money']
# 提取阅读人数数据
buy_count = data['buy_count']
# 打印 价钱和阅读人数
# print(pay_money)
# print(buy_count)
# 绘制散点图 (x, y)
plt.scatter(pay_money, buy_count)
# 设置 X横轴区间
plt.xlim(0, 36)
# 设置 Y横轴刻值
plt.xticks([0, 5, 10, 15, 20, 25, 30, 36])
# 设置 X横轴区间
plt.ylim(0, 7000)
# 设置 Y横轴刻值
plt.yticks([0, 1000, 2000, 3000, 4000, 5000, 6000, 7000])
# 计算回归线
# 将 pay_money 的值转换为二维数组
X = pay_money.values.reshape(-1, 1)
# 将 buy_count 的值转换为二维数组
y = buy_count.values.reshape(-1, 1)
# 创建回归线
reg = LinearRegression().fit(X, y)
# 使用拟合得到的模型 reg 对 X 进行预测,并且设置线条颜色
plt.plot(X, reg.predict(X), color='green')
# 设置 X轴注解
plt.xlabel('阅读人数')
# 设置 Y轴注解
plt.ylabel('价格')
# 设置 标题
plt.title('散点图 和 回归线')
# 将图片保存为 sd.png
plt.savefig('sd.png')
# 实时显示图片
plt.show()
if __name__ == "__main__":
# 中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
# 读取 CSV 文件
data = pd.read_csv('res.csv', encoding='gbk')
# 打印,对比结果
# print(data)
plot_reading_numbers(data)
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
import numpy as np
### 饼图:类型、购买人数
def plot_reading_numbers(data):
# 删除重复值(数据清洗)
data = data.drop_duplicates()
# print(data)
# 将清洗后的数据添加到 category_list 列表中
category_list = []
for item in data['category'].value_counts().index:
category_list.append(item)
# print(category_list)
# 设置比例图的每一块的颜色
colors = ['yellowgreen', 'gold', 'lightskyblue', 'lightcoral']
# print(data['category'].value_counts().values)
# 使用 matplotlib 库中的 plt.pie() 函数来绘制饼图
plt.pie(data['category'].value_counts().values, labels=category_list, autopct='%1.1f%%', startangle=90)
# 显示为圆(避免比例压缩为椭圆)
plt.axis('equal')
# 设置字体、并且支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']
# 保存饼图
plt.title('不同类型的购买人数的统计比例')
# 将图片保存为 bin.jpg
plt.savefig('bin.jpg')
# 实时显示图片
plt.show()
if __name__ == "__main__":
# 中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
# 读取 CSV 文件
data = pd.read_csv('res.csv', encoding='gbk')
# 打印,对比结果
# print(data)
plot_reading_numbers(data)
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
import numpy as np
### 直方图:类型、平均价格
def plot_reading_numbers(data):
# 对数据进行分组并计算平均价格
grouped_data = data.groupby('category')['pay_money'].mean()
# 绘制直方图
plt.bar(grouped_data.index, grouped_data.values)
# 设置 X 轴注解
plt.xlabel('类型')
# 设置 Y 轴注解
plt.ylabel('平均价格')
# 设置 标题
plt.title('同类型下平均价钱')
# 将图片保存为 zf.jpg
plt.savefig('zf.jpg')
# 实时显示图片
plt.show()
if __name__ == "__main__":
# 中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
# 读取 CSV 文件
data = pd.read_csv('res.csv', encoding='gbk')
# 打印,对比结果
# print(data)
plot_reading_numbers(data)
import pandas as pd
from wordcloud import WordCloud
import matplotlib.pyplot as plt
### 词云图:类型
def plot_reading_numbers(data):
# 提取title字段的数据
titles = ' '.join(data['title'])
# 设置字体文件的路径
font_path = 'simhei.ttf'
# 设置词云图的背景颜色
background_color = 'white'
# 设置词云图的宽度
width = 800
# 设置词云图的高度
height = 800
# 使用 generate() 方法生成词云图
wordcloud = WordCloud(font_path=font_path,
background_color=background_color,
width=width,
height=height).generate(titles)
# 使用imshow()方法显示词云图,并设置插值方式为双线性插值
plt.imshow(wordcloud, interpolation='bilinear')
# 关闭坐标轴
plt.axis('off')
# 将图片保存为 zf.jpg
plt.savefig('cy.jpg')
# 实时显示图片
plt.show()
if __name__ == "__main__":
# 中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
# 读取 CSV 文件
data = pd.read_csv('res.csv', encoding='gbk')
# 打印,对比结果
# print(data)
plot_reading_numbers(data)
标签:category,课程设计,plt,python,爬取,print,import,csv,data
From: https://www.cnblogs.com/YangSL23/p/17933133.html