Python高级应用程序设计任务
Posted ll55
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 = 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 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 Python高级应用程序设计任务