一、选题的背景(10分)
现如今汽车已逐步进入家庭中,对于一些准备购入新车的家庭,犹豫不决,不知道现在市场上与车友们推荐的哪些车,此次爬虫项目将对网上的团购排名进行爬取,更能简单直观的让大家依据个人情况来挑选自己中意的车辆详情。
二、设计方案(20分)
- 主题式网络爬虫名称
《python网络爬虫汽车团购报名的爬取及分析》
- 主题式网络爬虫爬取的内容与数据特征分析
爬取内容:2021年的汽车团购报名的前30
数据特征分析:2021年的汽车团购报名的排行榜的数据可通过后续绘制直方图、饼图、散点图等观察数据的比例以及变化情况。
3.主题式网络爬虫设计方案概述(包括实现思路与技术难点)
实现思路:本次设计方案主要使用requests库爬取网页信息BeautifulSoup库来提取2021年的汽车团购报名的排行榜前30的信息。
技术难点:主要包括爬取2021年的汽车团购报名的排行榜网站和对页面的解析,以及对爬取出的数据进行数据可视化分析。
4.主题页面的结构与特征分析
2021年的汽车团购报名的排行榜
- Htmls 页面解析:
2021年的汽车团购报名的排行榜源代码
- 节点(标签)查找方法与遍历方法 (必要时画出节点树结构)
查找方法:find_all(),select()
遍历方法:for循环
查找一:
<html>
<body>
<div>
<table>
<tbody>
< tr >
<td>
三、实现步骤及代码(60分)
1.数据爬取与采集
def getHTMLText(url): # 爬取页面中的信息
try:
r = requests.get(url, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return "产生异常"
def fillu(ulist, html):
soup = BeautifulSoup(html, 'html.parser')
for tr in soup.find_all('tr'):
if isinstance(tr, bs4.element.Tag):
tds = tr('td')
if tds == []:
continue
ulist.append([tds[0].string.strip(),tds[1].string.strip(), #将所需的数据加入到ulist的列表中
tds[2].string.strip(),tds[3].string.strip(),
tds[4].string.strip(),tds[5].string.strip().replace("分",""),
tds[6].string.strip().replace("L","")])
def printu(ulist, num):
print('{:^10}\t{:^6}\t{:^10}'.format('排名','车型','价格')) #格式化输出
for i in range(num):
u = ulist[i]
print('{:^10}\t{:^6}\t{:^10}'.format(u[0],u[1],u[2])) #输出排名、车型、价格
uinfo = []
url = 'https://top.16888.com/auto_rqbuy.html'
html = getHTMLText(url)
fillu(uinfo, html)
printu(uinfo, 30)
pm=[]
cx=[]
jg=[]
bml=[]
gzd=[]
kb=[]
yh=[]
#统计排名,车型,价格,报名量,关注度,口碑,油耗
for j in uinfo:
pm.append(eval(j[0]))
cx.append(j[1])
jg.append(j[2])
bml.append(eval(j[3]))
gzd.append(eval(j[4]))
yh.append(eval(j[6]))
if j[5]=='--':
kb.append(0)
else:
kb.append(eval(j[5]))
2.对数据进行清洗和处理
#对文件进行清洗
s=pd.DataFrame(pd.read_csv('D://2021年汽车团购报名排行榜.csv'))
# 删除重复值
s = s.drop_duplicates()
#报名量,关注度,口碑,油耗都不能为0将为0的删掉
s['报名量'].replace(0, np.nan, inplace=True)
s['关注度'].replace(0, np.nan, inplace=True)
s['口碑'].replace(0, np.nan, inplace=True)
s['油耗(L)'].replace(0, np.nan, inplace=True)
# 删除空值行
s = s.dropna()
# 保存处理后的数据,以便于数据可视化
s.to_csv("D://2021年汽车团购报名排行榜处理版.csv", index=False)
处理前:
处理后:
3.数据分析与可视化(例如:数据柱形图、直方图、散点图、盒图、分布图)
(1)饼图:
# 绘制车型和关注度的饼图
plt.figure(figsize=(30, 30)) # 做出数据可视化分析
name = n['车型'].values
rs = n['关注度'].values
explode = np.zeros(len(rs))
plt.legend(loc='center right')
plt.title('各种车型关注度的占比')
patches, l_text, p_text = plt.pie(rs,
explode=explode,
labels=name,
autopct='%1.1f%%',
shadow=False,
pctdistance=0.6,
labeldistance=1.1,
startangle=180,
radius=1.2,
counterclock=False,
textprops={'fontsize': 10, 'color': 'black'}
)
plt.legend(cx)
for t in p_text:
t.set_size(10)
for t in l_text:
t.set_size(10)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.axis('equal')
plt.show()
图:
(2) 折线图
# 绘制车型和报名量的折线图
plt.figure(figsize=(20, 6)) # 做出数据可视化分析
plt.style.use('ggplot')
plt.scatter(n['车型'].values, # x轴数据
n['报名量'].values, # y轴数据
linestyle='-', # 折线类型
linewidth=2, # 折线宽度
color='g', # 折线颜色
marker='o', # 折线图中添加的圆点
label='2021各国的增长率折线图',
)
plt.plot(n['车型'].values, n['报名量'].values, c="r")
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.xlabel('车型')
plt.ylabel('报名量')
plt.title("车型和报名量的折线图")
plt.legend(loc='upper left')
plt.show()
图:
(3)3D散点图
#绘制报名量、关注度、油耗3D散点图
fig=plt.figure("报名量、关注度、油耗的3D散点图",facecolor='lightgray')
ax=Axes3D(fig)
x=n['报名量'].values
y=n['关注度'].values
z=n['油耗(L)'].values
ax.scatter(x,y,z,s=20,cmap="jet",marker="o")
ax.set_xlabel('报名量')
ax.set_ylabel('关注度')
ax.set_zlabel('油耗(L)')
plt.title('报名量、关注度、油耗3D散点图',fontsize=20)
plt.show()
附图:
(4)柱状图
# 绘制车型和油耗的柱状图
Xl=n['车型'].values
Yl=n['油耗(L)'].values
# 中文乱码和坐标轴负号处理。
matplotlib.rc('font', family='SimHei', weight='bold')
plt.rcParams['axes.unicode_minus'] = False
#绘图。
fig, ax = plt.subplots()
b = ax.barh(range(len(Xl)), Yl, color='#6699CC')
#为横向水平的柱图右侧添加数据标签。
for rect in b:
w = rect.get_width()
ax.text(w, rect.get_y()+rect.get_height()/2, '%d' %
int(w), ha='left', va='center')
#设置Y轴纵坐标上的刻度线标签。
ax.set_yticks(range(len(Xl)))
ax.set_yticklabels(Xl)
#不要X横坐标上的label标签。
plt.xticks(())
plt.title('车型和油耗的柱状图', loc='center', fontsize='25',
fontweight='bold', color='red')
plt.show()
图:
4.根据数据之间的关系,分析两个变量之间的相关系数,画出散点图,并建立变量之间的回归方程(一元或多元)。
# 绘制排名和口碑的拟合曲线
def func(params, x):
a, b, c = params
return a * x * x + b * x + c
def error(params, x, y):
return func(params, x) - y
pxx = n['排名'].values
pyy = n['口碑'].values
params0 = [5, 2, 10]
Para = leastsq(error, params0, args=(pxx, pyy))
a, b, c = Para[0]
plt.figure(figsize=(20, 8))
plt.tick_params(labelsize=11)
plt.scatter(pxx, pyy, color='green', label="样本点")
x = data['排名'].values
y = a * x * x + b * x + c
plt.plot(x, y, color='red', label='拟合曲线')
plt.xlabel('排名')
plt.ylabel('口碑')
plt.title('排名和口碑的拟合曲线')
plt.legend()
plt.grid(True, linestyle='--',
color='g', linewidth='0.5')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.show()
# 绘制排名和报名量的拟合曲线
def func(params, x):
a, b, c = params
return a * x * x + b * x + c
def error(params, x, y):
return func(params, x) - y
px = n['排名'].values
py = n['报名量'].values
params0 = [5, 2, 10]
Para = leastsq(error, params0, args=(px, py))
a, b, c = Para[0]
plt.figure(figsize=(20, 8))
plt.tick_params(labelsize=11)
plt.scatter(px, py, color='green', label="样本点")
x = data['排名'].values
y = a * x * x + b * x + c
plt.plot(x, y, color='red', label='拟合曲线')
plt.xlabel('排名')
plt.ylabel('报名量')
plt.title('排名和报名量的拟合曲线')
plt.legend()
plt.grid(True, linestyle='--',
color='g', linewidth='0.5')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.show()
# 绘制排名和关注度的拟合曲线
def func(params, x):
a, b, c = params
return a * x * x + b * x + c
def error(params, x, y):
return func(params, x) - y
xi = n['排名'].values
yi = n['关注度'].values
params0 = [5, 2, 10]
Para = leastsq(error, params0, args=(xi, yi))
a, b, c = Para[0]
plt.figure(figsize=(20, 8))
plt.tick_params(labelsize=11)
plt.scatter(xi, yi, color='green', label="样本点")
x = data['排名'].values
y = a * x * x + b * x + c
plt.plot(x, y, color='red', label='拟合曲线')
plt.xlabel('排名')
plt.ylabel('关注度')
plt.title('排名和关注度的拟合曲线')
plt.legend()
plt.grid(True, linestyle='--',
color='b', linewidth='0.5')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.show()
图一:2021年人口的排名和人口数量的拟合曲线
图二:2021年人口的排名和增长率的拟合曲线
图三:2021年人口的排名和人口密度的拟合曲线
5.数据持久化
#将2021年人口数量、增长率、人口密度写入csv文件中
#将排名,车型,价格,报名量,关注度,口碑,油耗写入CSV文件中
data=pd.DataFrame({'排名':pm,'车型':cx,
'价格':jg,'报名量':bml,
'关注度':gzd,'口碑':kb,
'油耗(L)':yh})
data.to_csv("D://2021年汽车团购报名排行榜.csv", index=False)
6.将以上各部分的代码汇总,附上完整程序代码
import requests
from bs4 import BeautifulSoup
import bs4
import matplotlib
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import leastsq
from scipy import log
from scipy.optimize import curve_fit
from sklearn.metrics import r2_score
from mpl_toolkits.mplot3d import Axes3D
print("爬取2021年汽车团购报名排名前30名")
def getHTMLText(url): # 爬取页面中的信息
try:
r = requests.get(url, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return "产生异常"
def fillu(ulist, html):
soup = BeautifulSoup(html, 'html.parser')
for tr in soup.find_all('tr'):
if isinstance(tr, bs4.element.Tag):
tds = tr('td')
if tds == []:
continue
ulist.append([tds[0].string.strip(),tds[1].string.strip(), #将所需的数据加入到ulist的列表中
tds[2].string.strip(),tds[3].string.strip(),
tds[4].string.strip(),tds[5].string.strip().replace("分",""),
tds[6].string.strip().replace("L","")])
def printu(ulist, num):
print('{:^10}\t{:^6}\t{:^10}'.format('排名','车型','价格')) #格式化输出
for i in range(num):
u = ulist[i]
print('{:^10}\t{:^6}\t{:^10}'.format(u[0],u[1],u[2])) #输出排名、车型、价格
uinfo = []
url = 'https://top.16888.com/auto_rqbuy.html'
html = getHTMLText(url)
fillu(uinfo, html)
printu(uinfo, 30)
pm=[]
cx=[]
jg=[]
bml=[]
gzd=[]
kb=[]
yh=[]
#统计排名,车型,价格,报名量,关注度,口碑,油耗
for j in uinfo:
pm.append(eval(j[0]))
cx.append(j[1])
jg.append(j[2])
bml.append(eval(j[3]))
gzd.append(eval(j[4]))
yh.append(eval(j[6]))
if j[5]=='--':
kb.append(0)
else:
kb.append(eval(j[5]))
#将排名,车型,价格,报名量,关注度,口碑,油耗写入CSV文件中
data=pd.DataFrame({'排名':pm,'车型':cx,
'价格':jg,'报名量':bml,
'关注度':gzd,'口碑':kb,
'油耗(L)':yh})
data.to_csv("D://2021年汽车团购报名排行榜.csv", index=False)
#对文件进行清洗
s=pd.DataFrame(pd.read_csv('D://2021年汽车团购报名排行榜.csv'))
# 删除重复值
s = s.drop_duplicates()
#报名量,关注度,口碑,油耗都不能为0将为0的删掉
s['报名量'].replace(0, np.nan, inplace=True)
s['关注度'].replace(0, np.nan, inplace=True)
s['口碑'].replace(0, np.nan, inplace=True)
s['油耗(L)'].replace(0, np.nan, inplace=True)
# 删除空值行
s = s.dropna()
# 保存处理后的数据,以便于数据可视化
s.to_csv("D://2021年汽车团购报名排行榜处理版.csv", index=False)
#将清洗过的数据读取出来
n=pd.DataFrame(pd.read_csv('D://2021年汽车团购报名排行榜处理版.csv'))
# 绘制车型和关注度的饼图
plt.figure(figsize=(30, 30)) # 做出数据可视化分析
name = n['车型'].values
rs = n['关注度'].values
explode = np.zeros(len(rs))
plt.legend(loc='center right')
plt.title('各种车型关注度的占比')
patches, l_text, p_text = plt.pie(rs,
explode=explode,
labels=name,
autopct='%1.1f%%',
shadow=False,
pctdistance=0.6,
labeldistance=1.1,
startangle=180,
radius=1.2,
counterclock=False,
textprops={'fontsize': 10, 'color': 'black'}
)
plt.legend(cx)
for t in p_text:
t.set_size(10)
for t in l_text:
t.set_size(10)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.axis('equal')
plt.show()
# 绘制车型和报名量的折线图
plt.figure(figsize=(20, 6)) # 做出数据可视化分析
plt.style.use('ggplot')
plt.scatter(n['车型'].values, # x轴数据
n['报名量'].values, # y轴数据
linestyle='-', # 折线类型
linewidth=2, # 折线宽度
color='g', # 折线颜色
marker='o', # 折线图中添加的圆点
label='2021各国的增长率折线图',
)
plt.plot(n['车型'].values, n['报名量'].values, c="r")
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.xlabel('车型')
plt.ylabel('报名量')
plt.title("车型和报名量的折线图")
plt.legend(loc='upper left')
plt.show()
#绘制报名量、关注度、油耗3D散点图
fig=plt.figure("报名量、关注度、油耗的3D散点图",facecolor='lightgray')
ax=Axes3D(fig)
x=n['报名量'].values
y=n['关注度'].values
z=n['油耗(L)'].values
ax.scatter(x,y,z,s=20,cmap="jet",marker="o")
ax.set_xlabel('报名量')
ax.set_ylabel('关注度')
ax.set_zlabel('油耗(L)')
plt.title('报名量、关注度、油耗3D散点图',fontsize=20)
plt.show()
# 绘制车型和油耗的柱状图
Xl=n['车型'].values
Yl=n['油耗(L)'].values
# 中文乱码和坐标轴负号处理。
matplotlib.rc('font', family='SimHei', weight='bold')
plt.rcParams['axes.unicode_minus'] = False
#绘图。
fig, ax = plt.subplots()
b = ax.barh(range(len(Xl)), Yl, color='#6699CC')
#为横向水平的柱图右侧添加数据标签。
for rect in b:
w = rect.get_width()
ax.text(w, rect.get_y()+rect.get_height()/2, '%d' %
int(w), ha='left', va='center')
#设置Y轴纵坐标上的刻度线标签。
ax.set_yticks(range(len(Xl)))
ax.set_yticklabels(Xl)
#不要X横坐标上的label标签。
plt.xticks(())
plt.title('车型和油耗的柱状图', loc='center', fontsize='25',
fontweight='bold', color='red')
plt.show()
# 绘制排名和口碑的拟合曲线
def func(params, x):
a, b, c = params
return a * x * x + b * x + c
def error(params, x, y):
return func(params, x) - y
pxx = n['排名'].values
pyy = n['口碑'].values
params0 = [5, 2, 10]
Para = leastsq(error, params0, args=(pxx, pyy))
a, b, c = Para[0]
plt.figure(figsize=(20, 8))
plt.tick_params(labelsize=11)
plt.scatter(pxx, pyy, color='green', label="样本点")
x = data['排名'].values
y = a * x * x + b * x + c
plt.plot(x, y, color='red', label='拟合曲线')
plt.xlabel('排名')
plt.ylabel('口碑')
plt.title('排名和口碑的拟合曲线')
plt.legend()
plt.grid(True, linestyle='--',
color='g', linewidth='0.5')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.show()
# 绘制排名和报名量的拟合曲线
def func(params, x):
a, b, c = params
return a * x * x + b * x + c
def error(params, x, y):
return func(params, x) - y
px = n['排名'].values
py = n['报名量'].values
params0 = [5, 2, 10]
Para = leastsq(error, params0, args=(px, py))
a, b, c = Para[0]
plt.figure(figsize=(20, 8))
plt.tick_params(labelsize=11)
plt.scatter(px, py, color='green', label="样本点")
x = data['排名'].values
y = a * x * x + b * x + c
plt.plot(x, y, color='red', label='拟合曲线')
plt.xlabel('排名')
plt.ylabel('报名量')
plt.title('排名和报名量的拟合曲线')
plt.legend()
plt.grid(True, linestyle='--',
color='g', linewidth='0.5')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.show()
# 绘制排名和关注度的拟合曲线
def func(params, x):
a, b, c = params
return a * x * x + b * x + c
def error(params, x, y):
return func(params, x) - y
xi = n['排名'].values
yi = n['关注度'].values
params0 = [5, 2, 10]
Para = leastsq(error, params0, args=(xi, yi))
a, b, c = Para[0]
plt.figure(figsize=(20, 8))
plt.tick_params(labelsize=11)
plt.scatter(xi, yi, color='green', label="样本点")
x = data['排名'].values
y = a * x * x + b * x + c
plt.plot(x, y, color='red', label='拟合曲线')
plt.xlabel('排名')
plt.ylabel('关注度')
plt.title('排名和关注度的拟合曲线')
plt.legend()
plt.grid(True, linestyle='--',
color='b', linewidth='0.5')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.show()
四、总结(10分)
对主题数据的分析与可视化,能够将数据变得更加直观清晰,能够更好的对数据进行信息提取。此次排名可以看出团购汽车的排名和关注度是成正相关的,吸引大众的不仅仅是汽车的品牌也有对汽车的综合评分。
此次任务虽然说是完成了,但是还是有很多不足,在整个过程中,对知识掌握的不足导致于更多的需要在视频及朋友间寻求帮助才能够完成任务。但是在其中也是学到了很多东西,对编程这一方向有了更多兴趣。
标签:报名,plt,Python,取及,爬虫,color,values,关注度,params From: https://www.cnblogs.com/Autism0609/p/17456689.html