Python高级应用程序设计任务
Posted 黎达廷
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python高级应用程序设计任务相关的知识,希望对你有一定的参考价值。
Python高级应用程序设计任务要求
用Python实现一个面向主题的网络爬虫程序,并完成以下内容:
(注:每人一题,主题内容自选,所有设计内容与源代码需提交到博客园平台)
一、主题式网络爬虫设计方案(15分)
1.主题式网络爬虫名称
基于requests的携程旅游(北京景点)爬取和分析
2.主题式网络爬虫爬取的内容与数据特征分析
爬取内容包括景点的名称、评论量、分数。其数据特征有以下几点:
(1)分析景点、评分、评论数据,并进行清洗
(2)分析景点和评论数的关系,构建数据分析模型,观察模型图价格的分布情况。
3.主题式网络爬虫设计方案概述(包括实现思路与技术难点)
实现思路:
(1)利用requests方法请求网页。
(2)利用lxml进行网页解析,同时利用其语法获取需要的数据信息。
(3)利用循环实现翻页获取数据。
技术难点:
(1)要在爬取数据之前加入请求头部信息,否则会出现错误提示。
(2)注意要获取的数据在哪一个标签下,利用F12进行数据检查和分析所要爬取的数据特征。
二、主题页面的结构特征分析(15分)
1.主题页面的结构特征
查看源代码 li 对应着每一个攻略信息,都是静态页面,无ajax、js产生的动态数据。
2.Htmls页面解析
通过解析可以发现我们想要获取的楼房名称是在li标签下,dl下的a标签中。
3.节点(标签)查找方法与遍历方法
(必要时画出节点树结构)
三、网络爬虫程序设计(60分)
爬虫程序主体要包括以下各部分,要附源代码及较详细注释,并在每部分程序后面提供输出结果的截图。
1.数据爬取与采集
def pachong(): for i in range(1,10): url = \'https://you.ctrip.com/searchsite/sight/?query=%e5%8c%97%e4%ba%ac&isAnswered=&isRecommended=&publishDate=&PageNo=\'+str(i) res = get_tree(url) # 获取景点的列表 li_list = res.xpath(\'//ul[@class="jingdian-ul cf"]/li\') # 循环列表,拿取每一个数据 for li in li_list: dic = {} # # 景点名 name = li.xpath(\'./dl/dt/a[1]/text()\') dic[\'name\'] = name[0] # 保存景点图片,以景点名命名 picture = li.xpath(\'./a/img/@src\')[0] pic_url = picture # 因为有些图片地址路径不全,价格判断 if \'http\' not in picture: pic_url = \'https:\'+picture pic = requests.get(pic_url) dir = f\'./{name[0]}.png\' pinglun = li.xpath(\'./dl/dd/a/text()\') # 评论数量 dic[\'pinglun\'] = pinglun[0] xq_url = li.xpath(\'./a/@href\') # 详情页 xq_url = \'https://you.ctrip.com\'+xq_url[0] res1 = get_tree(xq_url) # 因为评分分两种格式,使用if判断拿取 fen = res1.xpath(\'//span[@class="score"]/b/text()\') if fen ==[]: fen1 = res1.xpath(\'//div[@class="score"]/span/i/text()\') dic[\'pingfen\'] = fen1[0] else: dic[\'pingfen\'] = fen[0] #保存数据 with open(\'景区.txt\',\'a\',encoding=\'utf8\') as fp2: fp2.write(str(dic)) fp2.write(\'\\n\') print(dic) time.sleep(1)
2.对数据进行清洗和处理
# 清洗数据 name = [] pinglun = [] pingfen = [] for i in data: lst1 = i.split(\',\') dic = {} for j in range(len(lst1)): dic[j] = lst1[j].split(\':\')[1].strip().replace("\'", "").replace(\'}\', \'\') name.append(dic[0]) pinglun.append(int(dic[1].replace(\'条点评\', \'\'))) pingfen.append(float(dic[2]))
3.文本分析(可选):jieba分词、wordcloud可视化
4.数据分析与可视化
(例如:数据柱形图、直方图、散点图、盒图、分布图、数据回归分析等)
5.数据持久化
6.附完整程序代码
import requests from lxml import etree import math import time import matplotlib.pyplot as plt import pandas as pd import json # 返回xpath数据 def get_tree(url): # 获取 网页内容,返回 xpath 数据 headers = { \'user-agent\':\'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36\' } res = requests.get(url=url,headers=headers).content.decode(\'utf-8\') # 保存网页,方便查看内容 # with open(\'qu.html\',\'w\',encoding=\'utf8\')as fp: # fp.write(res) res = etree.HTML(res) return res # 爬虫函数 def pachong(): for i in range(1,10): url = \'https://you.ctrip.com/searchsite/sight/?query=%e5%8c%97%e4%ba%ac&isAnswered=&isRecommended=&publishDate=&PageNo=\'+str(i) res = get_tree(url) # 获取景点的列表 li_list = res.xpath(\'//ul[@class="jingdian-ul cf"]/li\') # 循环列表,拿取每一个数据 for li in li_list: dic = {} # # 景点名 name = li.xpath(\'./dl/dt/a[1]/text()\') dic[\'name\'] = name[0] # 保存景点图片,以景点名命名 picture = li.xpath(\'./a/img/@src\')[0] pic_url = picture # 因为有些图片地址路径不全,价格判断 if \'http\' not in picture: pic_url = \'https:\'+picture pic = requests.get(pic_url) dir = f\'./{name[0]}.png\' pinglun = li.xpath(\'./dl/dd/a/text()\') # 评论数量 dic[\'pinglun\'] = pinglun[0] xq_url = li.xpath(\'./a/@href\') # 详情页 xq_url = \'https://you.ctrip.com\'+xq_url[0] res1 = get_tree(xq_url) # 因为评分分两种格式,使用if判断拿取 fen = res1.xpath(\'//span[@class="score"]/b/text()\') if fen ==[]: fen1 = res1.xpath(\'//div[@class="score"]/span/i/text()\') dic[\'pingfen\'] = fen1[0] else: dic[\'pingfen\'] = fen[0] #保存数据 with open(\'景区.txt\',\'a\',encoding=\'utf8\') as fp2: fp2.write(str(dic)) fp2.write(\'\\n\') print(dic) time.sleep(1) # 评分图绘制 def pingfentu(): # 读数据 with open(\'景区.txt\', \'r\', encoding=\'utf8\')as fp: data = fp.read() data = data.split(\'\\n\') # 清洗数据 name = [] pinglun = [] pingfen = [] for i in data: lst1 = i.split(\',\') dic = {} for j in range(len(lst1)): dic[j] = lst1[j].split(\':\')[1].strip().replace("\'", "").replace(\'}\', \'\') name.append(dic[0]) pinglun.append(int(dic[1].replace(\'条点评\', \'\'))) pingfen.append(float(dic[2])) data = {\'名字\': name, \'评论数\': pinglun, \'评分\': pingfen} # # 转为DataFrane 格式数据 df1 = pd.DataFrame(data) # 分析及绘图 # --------------------------------- # 评分图 plt.figure() # 修改默认字体 plt.rcParams[\'font.sans-serif\'] = \'SimHei\' # 正常显示符号,解决方块问题 plt.rcParams[\'axes.unicode_minus\'] = False pingfen1 = [i for i in df1[\'评分\']] group = [4.0 + i / 10 for i in range(11)] plt.hist(pingfen1, group, color=\'r\') plt.xlabel(\'评分\') plt.ylabel(\'数量\', rotation=0) plt.savefig(\'评分图.png\') plt.show() # 评论图绘制 def pingluntu(): with open(\'景区.txt\', \'r\', encoding=\'utf8\')as fp: data = fp.read() data = data.split(\'\\n\') # 清洗数据 name = [] pinglun = [] pingfen = [] for i in data: lst1 = i.split(\',\') dic = {} for j in range(len(lst1)): dic[j] = lst1[j].split(\':\')[1].strip().replace("\'", "").replace(\'}\', \'\') name.append(dic[0]) pinglun.append(int(dic[1].replace(\'条点评\', \'\'))) pingfen.append(float(dic[2])) data = {\'名字\': name, \'评论数\': pinglun, \'评分\': pingfen} # # 转为DataFrane 格式数据 df1 = pd.DataFrame(data) # 评论数前10绘图 df1_10 = df1.sort_values(by=\'评论数\', ascending=False)[:20] plt.figure() plt.rcParams[\'font.sans-serif\'] = \'SimHei\' # 正常显示符号,解决方块问题 plt.rcParams[\'axes.unicode_minus\'] = False x = [i for i in range(10)] plt.plot(x, df1_10[\'评论数\'][:10], color=\'g\', linestyle=\'-.\', marker=\'p\', markerfacecolor=\'r\') plt.xticks(x, df1_10[\'名字\'][:10], rotation=-45) for i in range(10): p = df1_10[\'评论数\'][i] plt.text(x[i], p + 100, \'%d条评论\' % p, horizontalalignment=\'center\') plt.savefig(\'评论图.png\') plt.show() if __name__ == \'__main__\': pachong() pingfentu() pingluntu()
四、结论(10分)
1.经过对主题数据的分析与可视化,可以得到哪些结论?
排除评论过少的景点,评分高的景点评论越多
2.对本次程序设计任务完成的情况做一个简单的小结。
经过这段时间对爬虫知识的学习,我对爬虫所使用的requests库、BeautifulSoup库、scrapy框架、lxml库有初步的认识,对爬虫的流程也有初步的了解。虽然这次爬取图片出了许多问题直到最后也没解决,希望自己以后能够爬取动态网页。
以上是关于Python高级应用程序设计任务的主要内容,如果未能解决你的问题,请参考以下文章