Python网络爬虫对汽车团购报名的爬取及分析

发布时间 2023-06-04 23:18:45作者: 李美萱

一、选题的背景(10分)

现如今汽车已逐步进入家庭中,对于一些准备购入新车的家庭,犹豫不决,不知道现在市场上与车友们推荐的哪些车,此次爬虫项目将对网上的团购排名进行爬取,更能简单直观的让大家依据个人情况来挑选自己中意的车辆详情。

二、设计方案(20分)

  1. 主题式网络爬虫名称

     python网络爬虫汽车团购报名的爬取及分析》

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

      爬取内容:2021年的汽车团购报名的前30

      数据特征分析:2021年的汽车团购报名的排行榜的数据可通过后续绘制直方图、饼图、散点图等观察数据的比例以及变化情况。

3.主题式网络爬虫设计方案概述(包括实现思路与技术难点) 

实现思路:本次设计方案主要使用requests库爬取网页信息BeautifulSoup库来提取2021年的汽车团购报名的排行榜前30的信息。

技术难点:主要包括爬取2021年的汽车团购报名的排行榜网站和对页面的解析,以及对爬取出的数据进行数据可视化分析。

4.主题页面的结构与特征分析

     2021年的汽车团购报名的排行榜

 

 

 

     

 

 

 

 

 

  1. Htmls 页面解析:

     2021年的汽车团购报名的排行榜源代码

    

 

      

 

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

查找方法: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分)

对主题数据的分析与可视化,能够将数据变得更加直观清晰,能够更好的对数据进行信息提取。此次排名可以看出团购汽车的排名和关注度是成正相关的,吸引大众的不仅仅是汽车的品牌也有对汽车的综合评分。

此次任务虽然说是完成了,但是还是有很多不足,在整个过程中,对知识掌握的不足导致于更多的需要在视频及朋友间寻求帮助才能够完成任务。但是在其中也是学到了很多东西,对编程这一方向有了更多兴趣。