码迷,mamicode.com
首页 > 编程语言 > 详细

Python高级应用程序设计任务

时间:2019-12-21 11:34:32      阅读:80      评论:0      收藏:0      [点我收藏+]

标签:持久化   一点   柱形图   ons   dict   pytho   字体   response   describe   

Python高级应用程序设计任务要求

用Python实现一个面向主题的网络爬虫程序,并完成以下内容:
(注:每人一题,主题内容自选,所有设计内容与源代码需提交到博客园平台)

一、主题式网络爬虫设计方案(15分)
1.主题式网络爬虫名称

爬取去哪儿所有攻略帖子数据及其分析

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

A、爬虫的内容

文章连接、标题、发布者、发布者的个人标签、出发日期、天数、拍照数量、出行的类型、旅行的标签、途经、行程路线、人均消费、观看数、点赞数、评论数

B、数据特征分析

b1、旅游天数分布图分图

b2、拍照数量分布图

b3、出行类型分布图

b4、各种出行方式人均消费箱型图

b5、对出行天数、拍照数量、人均消费、观看数、点赞数和评论数进行相关性分析

b6、人均消费价格和观看数的散点图分析

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

A、实现思路

  首先通过 get_page()方法获取网页的源码,然后通过 parse_page()方法提取所需要爬取的数据,将其设置为字典的格式,本文这里所采用的提取所用的工具是 bs4 中的 BeautifulSoup,使用的方法是 find 和find_all 方法,最后将爬取到的数据存储到 csv 文件之中。

B、技术难点

在数据提取的过程之中,存在有一定的难点,在爬取部分汉字内容时只能爬取下汉字所对应拼音内容。

二、主题页面的结构特征分析(15分)
1.主题页面的结构特征

本文爬取了共两百页数据,其中每页包含 10 条数据,总计两千条数据。

2.Htmls页面解析

需要爬取网站的数据如图所示:

技术图片

 

 

 

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

本文获得网页源码之后,主要是运用 BeautifulSoup 中的 find 和 find_all 来获取所需要的数据,节点部分如下图所示:

技术图片

可以看出,每条数据都在一个 li 标签下,因此使用 BeautifulSoup提取较为方便。

三、网络爬虫程序设计(60分)
爬虫程序主体要包括以下各部分,要附源代码及较详细注释,并在每部分程序后面提供输出结果的截图。
1.数据爬取与采集

爬虫代码如下所示:

# !/usr/bin/env python
# -*- coding:utf-8-*-

import requests
from bs4 import BeautifulSoup
import csv

headers = {User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36}
#获取网页源码
def get_page(url):
    response = requests.get(url,headers = headers)
    if response.status_code == 200:
        return response.text
    return None

#提取所需要爬取的数据
def parse_page(html):
    soup = BeautifulSoup(html,lxml)   #使用BeautifulSoup来解析网页
    tables = soup.find_all(li,class_ = list_item)   #每个数据所存储的节点位置
    #对每个节点遍历循环
    for table in tables:
        datas = {}
        datas[url] = https://travel.qunar.com + table.h2.a.get(href)
        datas[title] = table.h2.a.get_text()
        describe = table.h2.p
        datas[username] = table.find(class_ = user_name).a.get_text()
        label = table.find(class_ = user_name_icon)
        if label:
            datas[label] = label.get(title)
        datas[date] = table.find(class_ = date).get_text().replace(出发,‘‘)
        datas[days] = table.find(class_ = days).get_text().replace(,‘‘).replace(,‘‘)
        datas[photo_nums] = table.find(class_ = photo_nums).get_text().replace(张照片,‘‘)
        people = table.find(class_ = people)
        if people:
            datas[people] = people.get_text()
        trip = table.find(class_ = trip)
        if trip:
            datas[trip] = trip.get_text().replace(\xa0,)
        places = table.find_all(class_ = places)
        if places:
            datas[via_places] = places[0].get_text().replace(途经:,‘‘)
            if len(places) == 2:
                datas[distance] = places[1].get_text().replace(行程:,‘‘)
        price = table.find(class_ = fee)
        if price:
            datas[price] = price.get_text().replace(人均,‘‘).replace(,‘‘)
        view_nums = table.find(class_ = icon_view).get_text().replace(\ue09d,‘‘)
        if  in view_nums:
            datas[view_nums] = float(view_nums.replace(,‘‘)) * 10000
        else:
            datas[view_nums] = view_nums
        datas[praise_nums] = table.find(class_ = icon_love).get_text().replace(\uf04f,‘‘)
        datas[comment_nums] = table.find(class_ = icon_comment).get_text().replace(\uf060,‘‘)
        yield datas

#设置csv文件的标题
def write_csv_header(fileheader):
    with open("qunaer.csv", "a", newline=‘‘,encoding = utf-8) as csvfile:
        writer = csv.DictWriter(csvfile, fileheader)
        writer.writeheader()
 #将获取到的数据保存到csv
def save_to_csv(result,fileheader):
    with open("qunaer.csv", "a", newline=‘‘,encoding = utf-8) as csvfile:
        print(正在保存)
        writer = csv.DictWriter(csvfile, fieldnames=fileheader)
        writer.writerow(result)


if __name__ == __main__:
    fileheader = [url,title,username,label,date,days,photo_nums,people,trip,via_places,distance,price,view_nums,praise_nums,comment_nums]
    write_csv_header(fileheader)
    for page in range(1,201):   #爬取200页
        url = https://travel.qunar.com/travelbook/list.htm?page= + str(page) + &order=hot_heat
        html = get_page(url)
        datas = parse_page(html)
        for data in datas:
            save_to_csv(data,fileheader)

2.对数据进行清洗和处理

  在爬取数据的过程中,已经对数据做了一定的的清洗工作,如所其他的文章链接中不全,给他前面加上 https://travel.qunar.com,出发日期中的出发二字剔除,只取其中的日期部分,人均消费中如果含有万字,则删掉万字,并在原来数值的基础之上乘以 10000,天数中的共和天二字剔除,只取具体的天数部分,拍照数量中剔除张照片的字样,只取具体的拍照数量等。其中部分数据的某些指标为空值,但是不影响接下来继续分析。

3.文本分析(可选):jieba分词、wordcloud可视化
4.数据分析与可视化

(例如:数据柱形图、直方图、散点图、盒图、分布图、数据回归分析等)

导包

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

获取数据

#防止matplotlib中文乱码
plt.rcParams[font.sans-serif] = [KaiTi] # 指定默认字体
plt.rcParams[axes.unicode_minus] = False
#读取数据
data = pd.read_csv(qunaer.csv)

A、旅游天数分布图:

   实现代码如下所示:

#旅游天数分布图
date_count = data.groupby(days)[people].count().to_frame().reset_index()
_,ax = plt.subplots(figsize = (15,6))
sns.barplot(x = days,y = people,data = date_count,ax = ax )
ax.set_title(旅游天数分布图)
ax.set_xlabel(旅游天数)
ax.set_ylabel(次数)
plt.show()

  所得到的分布图如下图所示:

技术图片

B、拍照数量分布图

  代码如下图所示:

#拍照数量分布图
_,ax = plt.subplots(figsize = (15,6))
sns.distplot(data[photo_nums],kde = False,ax = ax)
ax.set_title(拍照数量分布图)
ax.set_xlabel(拍照数量)
ax.set_ylabel(数量)
plt.show()

  所得到的分布图如下所示:

技术图片

 

 

 

C、出行类型分布图

  代码如下图所示:

data_people = data.groupby(people)[trip].count().to_frame().reset_index()
_,ax = plt.subplots(figsize = (15,6))
sns.barplot(x = trip,y = people,data = data_people,orient = h,ax = ax)
ax.set_title(各种出行方式人数汇总)
ax.set_xlabel(人数)
ax.set_ylabel(出行方式)
plt.show()

  所得到的分布图如下所示:

技术图片

 

 

 

D、各种出行方式人均消费箱型图

  代码如下图所示:

_,ax = plt.subplots(figsize = (15,6))
sns.boxplot(x = people,y = price,data = data,ax = ax)
ax.set_title(各种出行方式人均消费箱型图)
ax.set_xlabel(出行方式)
ax.set_ylabel(人均消费)
plt.show()

  所得到的箱型图如下图所示:

技术图片

 

 

 E、对出行天数、拍照数量、人均消费、观看数、点赞数和评论数进行相关性分析,并作热力图可视化

  代码如下图所示:

#相关性分析
select_data = data[[days,photo_nums,price,view_nums,praise_nums,comment_nums]]
corr = select_data.corr()
print(corr)
sns.heatmap(corr)
plt.show()

  得到的相关性矩阵如下图所示:

技术图片

  所得到的热力图如下图所示:

  技术图片

 

 

 

F、人均消费价格和观看数的散点图分析

  代码如下图所示:

#散点图
_,ax = plt.subplots(figsize = (15,6))
sns.scatterplot(data[price],data[view_nums],ax = ax)
ax.set_xlabel(观看数)
ax.set_ylabel(人均消费价格)
plt.show()

  所得到的散点图如下图所示:

技术图片

5.数据持久化

将爬取到的数据以 csv 文件的格式存储起来,这样方便用 pandas 进行读取和分析。保存的数据格式如图所示:

技术图片

6.附完整程序代码

# !/usr/bin/env python
# -*- coding:utf-8-*-

import requests
from bs4 import BeautifulSoup
import csv
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

headers = {User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36}
#获取网页源码
def get_page(url):
    response = requests.get(url,headers = headers)
    if response.status_code == 200:
        return response.text
    return None

#提取所需要爬取的数据
def parse_page(html):
    soup = BeautifulSoup(html,lxml)   #使用BeautifulSoup来解析网页
    tables = soup.find_all(li,class_ = list_item)   #每个数据所存储的节点位置
    #对每个节点遍历循环
    for table in tables:
        datas = {}
        datas[url] = https://travel.qunar.com + table.h2.a.get(href)
        datas[title] = table.h2.a.get_text()
        describe = table.h2.p
        datas[username] = table.find(class_ = user_name).a.get_text()
        label = table.find(class_ = user_name_icon)
        if label:
            datas[label] = label.get(title)
        datas[date] = table.find(class_ = date).get_text().replace(出发,‘‘)
        datas[days] = table.find(class_ = days).get_text().replace(,‘‘).replace(,‘‘)
        datas[photo_nums] = table.find(class_ = photo_nums).get_text().replace(张照片,‘‘)
        people = table.find(class_ = people)
        if people:
            datas[people] = people.get_text()
        trip = table.find(class_ = trip)
        if trip:
            datas[trip] = trip.get_text().replace(\xa0,)
        places = table.find_all(class_ = places)
        if places:
            datas[via_places] = places[0].get_text().replace(途经:,‘‘)
            if len(places) == 2:
                datas[distance] = places[1].get_text().replace(行程:,‘‘)
        price = table.find(class_ = fee)
        if price:
            datas[price] = price.get_text().replace(人均,‘‘).replace(,‘‘)
        view_nums = table.find(class_ = icon_view).get_text().replace(\ue09d,‘‘)
        if  in view_nums:
            datas[view_nums] = float(view_nums.replace(,‘‘)) * 10000
        else:
            datas[view_nums] = view_nums
        datas[praise_nums] = table.find(class_ = icon_love).get_text().replace(\uf04f,‘‘)
        datas[comment_nums] = table.find(class_ = icon_comment).get_text().replace(\uf060,‘‘)
        yield datas

#设置csv文件的标题
def write_csv_header(fileheader):
    with open("qunaer.csv", "a", newline=‘‘,encoding = utf-8) as csvfile:
        writer = csv.DictWriter(csvfile, fileheader)
        writer.writeheader()
 #将获取到的数据保存到csv
def save_to_csv(result,fileheader):
    with open("qunaer.csv", "a", newline=‘‘,encoding = utf-8) as csvfile:
        print(正在保存)
        writer = csv.DictWriter(csvfile, fieldnames=fileheader)
        writer.writerow(result)


if __name__ == __main__:
    fileheader = [url,title,username,label,date,days,photo_nums,people,trip,via_places,distance,price,view_nums,praise_nums,comment_nums]
    write_csv_header(fileheader)
    for page in range(1,201):   #爬取200页
        url = https://travel.qunar.com/travelbook/list.htm?page= + str(page) + &order=hot_heat
        html = get_page(url)
        datas = parse_page(html)
        for data in datas:
            save_to_csv(data,fileheader)

#防止matplotlib中文乱码
plt.rcParams[font.sans-serif] = [KaiTi] # 指定默认字体
plt.rcParams[axes.unicode_minus] = False
#读取数据
data = pd.read_csv(qunaer.csv)
#旅游天数分布图
date_count = data.groupby(days)[people].count().to_frame().reset_index()
_,ax = plt.subplots(figsize = (15,6))
sns.barplot(x = days,y = people,data = date_count,ax = ax )
ax.set_title(旅游天数分布图)
ax.set_xlabel(旅游天数)
ax.set_ylabel(次数)
plt.show()

#拍照数量分布图
_,ax = plt.subplots(figsize = (15,6))
sns.distplot(data[photo_nums],kde = False,ax = ax)
ax.set_title(拍照数量分布图)
ax.set_xlabel(拍照数量)
ax.set_ylabel(数量)
plt.show()

#出行方式分布图
data_people = data.groupby(people)[trip].count().to_frame().reset_index()
_,ax = plt.subplots(figsize = (15,6))
sns.barplot(x = trip,y = people,data = data_people,orient = h,ax = ax)
ax.set_title(各种出行方式人数汇总)
ax.set_xlabel(人数)
ax.set_ylabel(出行方式)
plt.show()

#各种出行方式人均消费箱型图
_,ax = plt.subplots(figsize = (15,6))
sns.boxplot(x = people,y = price,data = data,ax = ax)
ax.set_title(各种出行方式人均消费箱型图)
ax.set_xlabel(出行方式)
ax.set_ylabel(人均消费)
plt.show()

#相关性分析
select_data = data[[days,photo_nums,price,view_nums,praise_nums,comment_nums]]
corr = select_data.corr()
print(corr)
sns.heatmap(corr)
plt.show()

#散点图
_,ax = plt.subplots(figsize = (15,6))
sns.scatterplot(data[price],data[view_nums],ax = ax)
ax.set_xlabel(观看数)
ax.set_ylabel(人均消费价格)
plt.show()

 

四、结论(10分)
1.经过对主题数据的分析与可视化,可以得到哪些结论?

a、通过对旅游天数的分布图分析,我们可以看出,大多数都是处于十天之内的,人们更偏好于短期旅游。

b、通过对拍照数量分布图进行可视化分析,可以得出大部分拍照数量处于 50-250 之间。

c、通过对出行类型类型的分布图进行可视化分析,可以看到三五好友的出行方式是最多的,其他像家庭,情侣,亲子的不少,因此可以得出人们更愿意结伴出游。

d、通过对各种出行方式人均消费箱型图进行可视化分析,可以看到以家庭、亲子、情侣的出行方式相对其他出行方式,人均消费更高。

e、相关性分析:通过对六个数值指标计算其相关系数矩阵,可以得出人均消费价格和出行天数之间存在较强的相关关系,平且两者之间具有正相关,拍照数量和出行天数也有一定的关系,但是其相关性相对较弱一点。

 f、通过对人均消费价格和观看数的散点图的可视化分析,可以看出两者之间存在一定的正相关关系,但是相关性关系较弱。

2.对本次程序设计任务完成的情况做一个简单的小结。

  通过这次的程序设计任务,我边编写边探索,实践、丰富了很多有关爬虫和数据分析相关的知识,更加明白了Python这门语言的便捷与乐趣,很感谢老师对这次实践作业的教导与陪伴,我会在将来的生活中逐渐用好这门神奇的课程。

Python高级应用程序设计任务

标签:持久化   一点   柱形图   ons   dict   pytho   字体   response   describe   

原文地址:https://www.cnblogs.com/eddieG/p/12073055.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!