一,主题式网络爬虫设计方案
1,主题式网络爬虫的名称
1.1步行街帖子的爬取
2,主题式网络爬虫的内容与数据特征分析
2.1爬虫的内容
标题,发布时间,回复数,浏览量,作者,声望,等级,社团,注册时间
2.2 数据特征分析
2.2.1社团做了一个柱状图
3,主题式网络爬虫设计方案概述(包括实现思路和技术难点)
3.1实现思路
创建一个球队的类和一个球员的累,定义master()方法作为启动程序,由于球员数据是一个相对稳定的数据, excel文件生成一次后不需要在另外进行生成, 所以通过pathlib.Path的方法检查excel文件是否存在,如果存在直接读取进行数据分析, 网站内容使用requests 和 beautifulsoup进行抓取,具体如下图解。
3.2技术难点
爬取过程中并未遇到阻拦,既不需要设置header, 也没遇到在爬取过程中被重定向到登录页面(整个爬取5-6分钟)。
二,主题页面的结构特征分析
1,主题页面的特征结构
通过查看接口详情,发现接口数据都是静态数据,直接通过分析网页的Dom数据就可以完成爬取,首先爬取新闻标题,然后根据标题的href地址取抓取对应的作者数据
2,HTML页面解析
这部分是截取的部分球员数据和球队标签
3,节点(标签)查找方法与遍历发法(必要时画出节点数结构)
查找节点的方法采用beautifoulSoup的元素选择器,通过find,select等内置方法来来提取所需要的数据。从整体(tbody)到部分(tr)的查找方式,即先确定爬取的数据所在哪个html的节点中,找到这个节点的所有直接子节点,也就是每一个攻略项,再用for循环依次遍历,然后再具体解析遍历的每一项攻略的数据,图解如下。
三,网络爬虫程序设计
1,爬虫程序主题要包括以下部分,要附源代码及较详解注释,并在每部分程序后面提供输出结果的截图。
import requests from bs4 import BeautifulSoup import openpyxl import pathlib import pandas as pd import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties def show(): df = pd.read_excel("步行街.xlsx") team = df["社团"].dropna() res = {} keys = [] values = [] for item in team: if item in res: res[item] = res[item] + 1 else: res[item] = 1 for val in res: keys.append(val) values.append(res[val]) fig = plt.figure() font = FontProperties(fname="/System/Library/Fonts/STHeiti Medium.ttc") plt.barh(keys, values, 0.8) plt.yticks(fontproperties=font, size="small", rotation=30, fontsize=10) plt.xlabel("X", fontproperties=font) plt.ylabel("Y", fontproperties=font) plt.show() plt.savefig("./bxj.png") def write_to_excel(posts): book_name = "步行街.xlsx" sheet_name = "步行街" columns = ["标题", "发布时间", "回复", "浏览量", "作者", "声望", "等级", "社团", "注册时间"] path = pathlib.Path(book_name) is_new = False # 检查文件是否存在, 不存在的创建一个文件 if not path.exists(): workbook = openpyxl.Workbook() sheet = workbook.active # 设置sheet的名称 sheet.title = sheet_name index = 1 is_new = True else: workbook = openpyxl.load_workbook(book_name) sheet = workbook[sheet_name] sheet.title = sheet_name index = sheet.max_row # 插入标题栏 if is_new: for i in range(0, len(columns)): sheet.cell(index, i + 1, columns[i]) for key, value in posts.items(): index += 1 sheet.cell(index, 1, value.title) sheet.cell(index, 2, value.create) sheet.cell(index, 3, value.reply) sheet.cell(index, 4, value.view) sheet.cell(index, 5, value.author.name) sheet.cell(index, 6, value.author.reputation) sheet.cell(index, 7, value.author.level) sheet.cell(index, 8, value.author.organization) sheet.cell(index, 9, value.author.join_time) workbook.save(book_name) class Author: def __init__(self, name, address): self.name = name self.address = address self.reputation = 0 self.level = 0 self.join_time = 0 self.organization = "" def get_message(self): response = requests.get(self.address) if response.status_code != 200: print("获取用户 [%s] 主页信息 [%s] 失败" % self.name, self.address) return content = response.content ct = response.headers["Content-Type"].split("charset=")[1].lower() bs4 = BeautifulSoup(content, features="html.parser", from_encoding=ct) person = bs4.find("div", class_="personalinfo") try: self.organization = person.select_one("span[itemprop=memberOf]").get_text() except BaseException: print("memberof not found. " + self.address + ";" + self.name) rk = -1 lk = -1 jk = -1 if person is None: print("the user [%s %s] not found children message" % (self.name, self.address)) return for key, child in enumerate(person.children): if rk == key: self.reputation = child.string.strip() elif lk == key: self.level = child.string.strip() elif jk == key: self.join_time = child.string.split("年")[0] if child.string is not None: # 检查到声望, 下一个字段为具体的声望 rd = child.string.strip().find("声望") if rd >= 0: rk = key + 1 # 检查到等级, 下一个字段为具体等级 ld = child.string.strip().find("等级") if ld >= 0: lk = key + 1 # 检查到加入时间, 下一个字段加入时间 jd = child.string.strip().find("加入时间") if jd >= 0: jk = key + 1 class Post: def __init__(self, title, href, author, reply, view, create): self.title = title self.href = href self.author = author self.reply = reply self.view = view self.create = create def master(): base = "https://bbs.hupu.com/bxj" prefix = "https://bbs.hupu.com" for i in range(1, 21): posts = {} url = base + "-%d" % i response = requests.get(url) if response.status_code != 200: print("resquest hupu error, page %d" % i) continue content = response.content ct = response.headers["Content-Type"].split("charset=")[1].lower() bs4 = BeautifulSoup(content, from_encoding=ct, features="html.parser") # 获取所有的帖子 pl = bs4.find("ul", class_="for-list") if pl is None: continue pl = pl.find_all("li") for item in pl: # if len(posts) >= 3: # break # title Dom td = item.select_one(".titlelink > a") # 文章标题 title = td.get_text() href = prefix + td["href"] # 作者Dom ad = item.select(".author > a") # 作者主页 ah = ad[0]["href"] # 作者名称 author = ad[0].get_text() # 用户实例 ac = Author(author, ah) ac.get_message() # 文章的创建时间 create = ad[1].get_text() # 浏览量 Dom rd = item.select_one(".ansour").get_text() # 获取浏览量以及回复量 sp = rd.split("/") # 回复量 reply = sp[0] # 浏览量 view = sp[1] post = Post(title, href, ac, reply, view, create) posts[title] = post write_to_excel(posts) # 步行街 if __name__ == "__main__": name = "步行街.xlsx" path = pathlib.Path(name) # if not path.exists(): master() # else: # show()
数据可视化
5.数据持久化
写入csv文件
四、结论(10分)
1.经过对主题数据的分析与可视化,可以得到哪些结论?
1.1 虽然有些帖子的浏览数很多但是评论数很低,说明这种帖子的质量较低,可以忽略。
1.2 大部分人的声望为整数
2.对本次程序设计任务完成的情况做一个简单的小结。
本次作业, 通过运用了学习到的爬虫和数据分析的知识分析了虎扑步行街的相关情况,为自己以后工作奠定了基础,同时也在思考了之后比如在多线程或者数据的持久化方面的知识,为自己取得的成就感到高兴
原文:https://www.cnblogs.com/niuniu123/p/12070691.html