Python高级应用程序设计任务,,Python高级应用
Python高级应用程序设计任务,,Python高级应用
Python高级应用程序设计任务要求
用Python实现一个面向主题的网络爬虫程序,并完成以下内容:
(注:每人一题,主题内容自选,所有设计内容与源代码需提交到博客园平台)
一、主题式网络爬虫设计方案(15分)
1.主题式网络爬虫名称
穷游网香港旅游攻略中的景点爬取
2.主题式网络爬虫爬取的内容与数据特征分析
内容:主要爬取穷游网香港旅游攻略景点排名前100的旅游景点的信息,以及对应的景点评论信息。
数据特征分析:对所有的评论做了词云、对景点的评分做了可视化和柱状图
3.主题式网络爬虫设计方案概述(包括实现思路与技术难点)
实现思路:首先通过分析此网站得知数据的传输通过ajax实现,其中景点信息固定url为“https://place.qyer.com/poi.php?action=list_json”,通过修改data参数实现翻页。创建一个ScenicInfo 类定义param_info和insert实现对数据的抓取和保存。景点评论信息是通过url拼接来实现,创建一个Comments类定义param_comments发起请求获得json数据,insert方法插入数据库
技术难点:在爬取过程中没有出现反爬。
二、主题页面的结构特征分析(15分)
1.主题页面的结构特征
每页15项数据,爬取了64页,一共960项数据。通过chrome抓包调试发现所有得数据都是通过ajax动态发送只需修改post参数几个。
2.Htmls页面解析
红框中的数据为爬取字段
三、网络爬虫程序设计(60分)
爬虫程序主体要包括以下各部分,要附源代码及较详细注释,并在每部分程序后面提供输出结果的截图。
1.数据爬取与采集
1、景点信息的采集与爬取
1 # 景点信息的采集与爬取 2 import pymysql 3 import requests 4 5 # 定义类名和设置默认参数 6 class ScenicInfo(object): 7 def __init__(self): 8 # 要获取的url 9 self.url = ‘https://place.qyer.com/poi.php?action=list_json‘10 # 设置请求头11 self.headers = {12 ‘user-agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36‘,13 ‘referer‘: ‘https://place.qyer.com/hong-kong/sight/‘14 }15 # 对数据进行清洗和处理16 def param_info(self, form_data):17 # 通过request发起请求18 resp = requests.post(self.url, form_data, headers=self.headers)19 # 获得返回json数据解析20 data = resp.json()[‘data‘][‘list‘]21 # 遍历返回的数据,将数据插入数据库22 for index in data:23 print(index[‘id‘], index[‘cnname‘], index[‘rank‘], index[‘grade‘], index[‘url‘], index[‘commentCount‘])24 # 执行操作数据库的方法25 self.insert(index[‘id‘], index[‘cnname‘], index[‘rank‘], index[‘grade‘], index[‘url‘],26 index[‘commentCount‘])27 28 def run(self):29 # 通过遍历来改变post的参数,来实现翻页30 for page in range(1, 65):31 print(‘当前正在采集第%s页!‘ % str(page))32 form_data = {33 ‘page‘: page,34 ‘type‘: ‘city‘,35 ‘pid‘: ‘50‘,36 ‘sort‘: ‘32‘,37 ‘subsort‘: ‘all‘,38 ‘isnominate‘: ‘-1‘,39 ‘haslastm‘: ‘false‘,40 ‘rank‘: ‘6‘,41 }42 # 将带着参数传入这个方法,然后发起请求43 self.param_info(form_data)44 # 数据持久化45 def insert(*details):46 # 连接数据库47 db = pymysql.connect("localhost", "root", "root", "honk")48 # 获得游标49 cursor = db.cursor()50 # 设置sql语句51 sql = "insert into scenic (cid,name,rank,grade,url,comment_count)value(%s,%s,%s,%s,%s,%s)"52 # 执行sql语句53 try:54 cursor.execute(sql, details)55 db.commit()56 print(‘插入数据成功‘)57 except Exception as e:58 db.rollback()59 print("插入数据失败", e)60 db.close()61 62 if __name__ == ‘__main__‘:63 scenicInfo = ScenicInfo()64 scenicInfo.run()
2、景点评论信息的采集与爬取
1 # 景点评论的采集和爬取 2 import re 3 4 import redis 5 import requests 6 7 import pymysql 8 from redis import StrictRedis 9 10 # 定义类名和设置默认参数11 class Comments(object):12 def __init__(self):13 self.r = StrictRedis(host=‘localhost‘, port=6379, db=0, decode_responses=True)14 # 设置请求头15 self.headers = {16 ‘user-agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36‘17 }18 # 获取评论信息19 def param_comments(self, code):20 page = 121 # 要获取的url22 url = ‘https://place.qyer.com/poi.php?action=comment&page={}&order=5&poiid={}&starLevel=all‘.format(page, code)23 print(url)24 # 通过request发起请求25 resp = requests.post(url, headers=self.headers)26 # 获得返回json数据分析27 data = resp.json()[‘data‘][‘lists‘]28 # 判断数据是否为空29 if len(data) != 0:30 # 通过正则匹配的title31 try:32 total = resp.json()[‘data‘][‘pagehtml‘]33 total_page = re.findall(‘title="(.*?)"‘, total)[0].replace(‘...‘, ‘‘)34 35 except Exception as e:36 total_page = 137 38 print(‘当前总页数:%s‘ % total_page)39 # 判断有多少页,若返回的信息是下一页就设置为1,否则就用抓取到的页数40 if total_page == ‘下一页‘:41 total_page = 142 for page in range(1, int(total_page) + 1):43 print("当前总共%s页,正在采集第%s页!" % (total_page, page))44 # 对数据进行清洗和处理45 url = ‘https://place.qyer.com/poi.php?action=comment&page={}&order=5&poiid={}&starLevel=all‘.format(46 page,47 code)48 # 通过request发起请求49 resp = requests.post(url, headers=self.headers)50 # 获得返回json数据分析51 data = resp.json()[‘data‘][‘lists‘]52 # 遍历返回的数据,将数据插入数据库53 for index in data:54 name = index[‘userinfo‘][‘name‘]55 starlevel = index[‘starlevel‘]56 content = index[‘content‘]57 date = index[‘date‘]58 print(code, name, starlevel, content, date)59 # 将带着参数传入这个方法,然后发起请求60 self.insert(code, name, starlevel, content, date)61 # 数据持久化62 def insert(self, *details):63 # 连接数据库64 db = pymysql.connect("localhost", "root", "root", "honk")65 # 获得游标66 cursor = db.cursor()67 # 设置sql语句68 sql = "insert into comments (sid,name,starlevel,content,date)value(%s,%s,%s,%s,%s)"69 # 执行sql语句70 try:71 cursor.execute(sql, details)72 db.commit()73 print(‘插入数据成功‘)74 except Exception as e:75 db.rollback()76 print("插入数据失败", e)77 db.close()78 # 设置死循环,从缓存里面拿到景点的code然后拼接成url79 def run(self):80 while True:81 code = self.r.lpop(‘h_code‘)82 83 if code is None:84 print("当前url请求结束!")85 break86 87 self.param_comments(code)88 89 90 if __name__ == ‘__main__‘:91 comments = Comments()92 comments.run()
2.对数据进行清洗和处理
1、对景点信息数据进行清洗和处理
2、对景点评论数据进行清洗和处理
3.文本分析(可选):jieba分词、wordcloud可视化
1 from wordcloud import WordCloud 2 import matplotlib.pyplot as plt 3 import jieba 4 5 # 生成词云 6 def create_word_cloud(filename): 7 text = open("{}.txt".format(filename), encoding=‘utf-8‘).read() 8 # 结巴分词 9 wordlist = jieba.cut(text, cut_all=True)10 wl = " ".join(wordlist)11 12 # 设置词云13 wc = WordCloud(14 # 设置背景颜色15 background_color="white",16 # 设置最大显示的词云数17 max_words=2000,18 # 这种字体都在电脑字体中,一般路径19 font_path=‘C:\Windows\Fonts\simfang.ttf‘,20 height=1200,21 width=1600,22 # 设置字体最大值23 max_font_size=100,24 # 设置有多少种随机生成状态,即有多少种配色方案25 random_state=30,26 )27 28 myword = wc.generate(wl) # 生成词云29 # 展示词云图30 plt.imshow(myword)31 plt.axis("off")32 plt.show()33 wc.to_file(‘comments.png‘) # 把词云保存下来34 35 if __name__ == ‘__main__‘:36 create_word_cloud(‘comments‘)
4.数据分析与可视化
(例如:数据柱形图、直方图、散点图、盒图、分布图、数据回归分析等)
1 import pymysql 2 import matplotlib.pyplot as plt 3 4 db = pymysql.connect(host="localhost", user=‘root‘, passwd="root", port=3306, db="honk", charset=‘utf8‘) 5 cursor = db.cursor() # 获取一个游标 6 sql = "select name,grade from scenic" 7 cursor.execute(sql) 8 result = cursor.fetchall() # result为元组 9 10 # 将元组数据存进列表中11 city = []12 need = []13 for x in result:14 city.append(x[0])15 need.append(float(x[1]))16 17 # 直方图18 plt.bar(range(len(need)), need, color=‘steelblue‘, tick_label=city)19 plt.xlabel("景点")20 plt.ylabel("评分")21 plt.title("城市职位需求图")22 for x, y in enumerate(need):23 plt.text(x - 2, y + 2, ‘%s‘ % y)24 plt.show()25 cursor.close() # 关闭游标26 db.close() # 关闭数据库
5.数据持久化
1、景点信息数据持久化
2、景点评论信息数据持久化
6.附完整程序代码
1 # 景点评论的采集和爬取 2 import re 3 4 import redis 5 import requests 6 7 import pymysql 8 from redis import StrictRedis 9 10 # 定义类名和设置默认参数 11 class Comments(object): 12 def __init__(self): 13 self.r = StrictRedis(host=‘localhost‘, port=6379, db=0, decode_responses=True) 14 # 设置请求头 15 self.headers = { 16 ‘user-agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36‘ 17 } 18 # 获取评论信息 19 def param_comments(self, code): 20 page = 1 21 # 要获取的url 22 url = ‘https://place.qyer.com/poi.php?action=comment&page={}&order=5&poiid={}&starLevel=all‘.format(page, code) 23 print(url) 24 # 通过request发起请求 25 resp = requests.post(url, headers=self.headers) 26 # 获得返回json数据分析 27 data = resp.json()[‘data‘][‘lists‘] 28 # 判断数据是否为空 29 if len(data) != 0: 30 # 通过正则匹配的title 31 try: 32 total = resp.json()[‘data‘][‘pagehtml‘] 33 total_page = re.findall(‘title="(.*?)"‘, total)[0].replace(‘...‘, ‘‘) 34 35 except Exception as e: 36 total_page = 1 37 38 print(‘当前总页数:%s‘ % total_page) 39 # 判断有多少页,若返回的信息是下一页就设置为1,否则就用抓取到的页数 40 if total_page == ‘下一页‘: 41 total_page = 1 42 for page in range(1, int(total_page) + 1): 43 print("当前总共%s页,正在采集第%s页!" % (total_page, page)) 44 # 对数据进行清洗和处理 45 url = ‘https://place.qyer.com/poi.php?action=comment&page={}&order=5&poiid={}&starLevel=all‘.format( 46 page, 47 code) 48 # 通过request发起请求 49 resp = requests.post(url, headers=self.headers) 50 # 获得返回json数据分析 51 data = resp.json()[‘data‘][‘lists‘] 52 # 遍历返回的数据,将数据插入数据库 53 for index in data: 54 name = index[‘userinfo‘][‘name‘] 55 starlevel = index[‘starlevel‘] 56 content = index[‘content‘] 57 date = index[‘date‘] 58 print(code, name, starlevel, content, date) 59 # 将带着参数传入这个方法,然后发起请求 60 self.insert(code, name, starlevel, content, date) 61 # 数据持久化 62 def insert(self, *details): 63 # 连接数据库 64 db = pymysql.connect("localhost", "root", "root", "honk") 65 # 获得游标 66 cursor = db.cursor() 67 # 设置sql语句 68 sql = "insert into comments (sid,name,starlevel,content,date)value(%s,%s,%s,%s,%s)" 69 # 执行sql语句 70 try: 71 cursor.execute(sql, details) 72 db.commit() 73 print(‘插入数据成功‘) 74 except Exception as e: 75 db.rollback() 76 print("插入数据失败", e) 77 db.close() 78 # 设置死循环,从缓存里面拿到景点的code然后拼接成url 79 def run(self): 80 while True: 81 code = self.r.lpop(‘h_code‘) 82 83 if code is None: 84 print("当前url请求结束!") 85 break 86 87 self.param_comments(code) 88 90 if __name__ == ‘__main__‘: 91 comments = Comments() 92 comments.run() 93 94 # 景点信息的采集与爬取 95 import pymysql 96 import requests 97 98 # 定义类名和设置默认参数 99 class ScenicInfo(object):100 def __init__(self):101 # 要获取的url102 self.url = ‘https://place.qyer.com/poi.php?action=list_json‘103 # 设置请求头104 self.headers = {105 ‘user-agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36‘,106 ‘referer‘: ‘https://place.qyer.com/hong-kong/sight/‘107 }108 # 对数据进行清洗和处理109 def param_info(self, form_data):110 # 通过request发起请求111 resp = requests.post(self.url, form_data, headers=self.headers)112 # 获得返回json数据解析113 data = resp.json()[‘data‘][‘list‘]114 # 遍历返回的数据,将数据插入数据库115 for index in data:116 print(index[‘id‘], index[‘cnname‘], index[‘rank‘], index[‘grade‘], index[‘url‘], index[‘commentCount‘])117 # 执行操作数据库的方法118 self.insert(index[‘id‘], index[‘cnname‘], index[‘rank‘], index[‘grade‘], index[‘url‘],119 index[‘commentCount‘])120 121 def run(self):122 # 通过遍历来改变post的参数,来实现翻页123 for page in range(1, 65):124 print(‘当前正在采集第%s页!‘ % str(page))125 form_data = {126 ‘page‘: page,127 ‘type‘: ‘city‘,128 ‘pid‘: ‘50‘,129 ‘sort‘: ‘32‘,130 ‘subsort‘: ‘all‘,131 ‘isnominate‘: ‘-1‘,132 ‘haslastm‘: ‘false‘,133 ‘rank‘: ‘6‘,134 }135 # 将带着参数传入这个方法,然后发起请求136 self.param_info(form_data)137 # 数据持久化138 def insert(*details):139 # 连接数据库140 db = pymysql.connect("localhost", "root", "root", "honk")141 # 获得游标142 cursor = db.cursor()143 # 设置sql语句144 sql = "insert into scenic (cid,name,rank,grade,url,comment_count)value(%s,%s,%s,%s,%s,%s)"145 # 执行sql语句146 try:147 cursor.execute(sql, details)148 db.commit()149 print(‘插入数据成功‘)150 except Exception as e:151 db.rollback()152 print("插入数据失败", e)153 db.close()154 155 if __name__ == ‘__main__‘:156 scenicInfo = ScenicInfo()157 scenicInfo.run()158 159 from wordcloud import WordCloud160 import matplotlib.pyplot as plt161 import jieba162 163 # 生成词云164 def create_word_cloud(filename):165 text = open("{}.txt".format(filename), encoding=‘utf-8‘).read()166 # 结巴分词167 wordlist = jieba.cut(text, cut_all=True)168 wl = " ".join(wordlist)169 170 # 设置词云171 wc = WordCloud(172 # 设置背景颜色173 background_color="white",174 # 设置最大显示的词云数175 max_words=2000,176 # 这种字体都在电脑字体中,一般路径177 font_path=‘C:\Windows\Fonts\simfang.ttf‘,178 height=1200,179 width=1600,180 # 设置字体最大值181 max_font_size=100,182 # 设置有多少种随机生成状态,即有多少种配色方案183 random_state=30,184 )185 # 生成词云186 myword = wc.generate(wl)187 # 展示词云图188 plt.imshow(myword)189 plt.axis("off")190 plt.show()191 # 把词云保存下来192 wc.to_file(‘comments.png‘)193 194 if __name__ == ‘__main__‘:195 create_word_cloud(‘comments‘)196 198 import pymysql199 import matplotlib.pyplot as plt200 201 db = pymysql.connect(host="localhost", user=‘root‘, passwd="root", port=3306, db="honk", charset=‘utf8‘)202 # 获取一个游标203 cursor = db.cursor()204 sql = "select name,grade from scenic"205 cursor.execute(sql)206 # result为元组207 result = cursor.fetchall()208 209 # 将元组数据存进列表中210 city = []211 need = []212 for x in result:213 city.append(x[0])214 need.append(float(x[1]))215 216 # 直方图217 plt.bar(range(len(need)), need, color=‘steelblue‘, tick_label=city)218 plt.xlabel("景点")219 plt.ylabel("评分")220 plt.title("城市职位需求图")221 for x, y in enumerate(need):222 plt.text(x - 2, y + 2, ‘%s‘ % y)223 plt.show()224 # 关闭游标225 cursor.close()226 # 关闭数据库227 db.close()228 229 import json, redis230 231 # 连接数据库232 def my_db(table_name):233 import pymysql234 coon = pymysql.connect(235 user=‘root‘, passwd=‘root‘, host=‘127.0.0.1‘, port=3306,236 db=‘honk‘, charset=‘utf8‘237 )238 # 建立游标,指定cursor类型返回的是字典239 cur = coon.cursor(cursor=pymysql.cursors.DictCursor)240 # cur = coon.cursor()241 sql = ‘select cid from %s ;‘ % table_name242 data = cur.execute(sql)243 # 关闭数据库连接244 cur.close()245 coon.close()246 return cur.fetchall()247 248 # 对景点urlcode进行去重249 def removal_set(all_date):250 comments_code = set()251 for date in all_date:252 print(date)253 key = date.get(‘sid‘)254 comments_code.add(key)255 print(key)256 return comments_code257 258 # 将code的值添加到缓存里259 def add_redis(comments_code):260 r = redis.Redis(host=‘127.0.0.1‘, password=‘‘, db=0) # 端口号默认6379261 for data in comments_code:262 r.lpush(‘h_code‘, data["cid"])263 print(‘添加完毕!‘)264 265 # 从缓存里面获取code266 def get_redis():267 r = redis.Redis(host=‘127.0.0.1‘, password=‘‘, db=0) # 端口号默认6379268 r.lpop(‘h_code‘)269 270 # 删除code271 def del_redis():272 r = redis.Redis(host=‘127.0.0.1‘, password=‘‘, db=0) # 端口号默认6379273 r.delete(‘h_code‘)274 print("key删除成功!")275277 if __name__ == ‘__main__‘:278 all_data = my_db(‘scenic‘)279 280 # comments_code = removal_set(all_data)281 282 add_redis(all_data)283 # del_redis()284 # get_redis()
四、结论(10分)
1.经过对主题数据的分析与可视化,可以得到哪些结论?
1、太平山的景点综合排名为第一名
2、多数人来香港都会到维多利亚港、太平山和海洋公园
3、来香港旅游的人还是很多的。
2.对本次程序设计任务完成的情况做一个简单的小结。
答:这次的程序设计任务对我来说是一个新的挑战也是一项难度较高的任务,从原有的课本到书店查看相关书籍到关于python语言和网络爬虫的网课学习 ,由最开始的编程小白渐渐地学会了如何去写代码如何去一步步解决问题。最开始一直害怕的是网站反爬问题,不过幸好后来没有遇到这个问题。历时一个多月我终于完成了这份艰巨的任务,这次的挑战,让我学习和看到了新的不一样的东西,收获了许多新的知识。希望自己以后能够继续进步继续努力。
Python高级应用程序设计任务
相关内容
- python3编译安装,, linux下配置安
- 《机器学习实战》--KNN,,代码来自《机器学习实
- Python-EEG工具库MNE中文教程(10)-信号空间投影SSP数学原理
- 列表反转函数,,列表反转函数一:#!
- python批量执行脚本,使用unittest.TestSuit(); unittest.TextTe
- Python可视化 | Seaborn包—kdeplot和distplot,,import pan
- Python数字(Number),,Python 数字数
- python-docx,,pip instal
- Python——函数的参数,, 定义函数的时候,
- python(静态,组合,继承),,静态属性用@prop
评论关闭