100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 爬虫爬取知乎评论并利用flask框架做简单的可视化

爬虫爬取知乎评论并利用flask框架做简单的可视化

时间:2023-05-26 01:15:59

相关推荐

爬虫爬取知乎评论并利用flask框架做简单的可视化

学完一点简单的爬虫技术后,直接开始实践…

将知乎的某个评论内容爬取下来,取出里面的关键字,并按照点赞数排序,形成一个表单,点击查看,可以看到原来的内容,比如下面这个网页:

python能做那些有趣还很酷的事

我们发现右边的下拉条是拉不到底的,而且打开开发者模式,发现拉一点,他就加载一点,我们需要循环拉到底

,然后获取整个网页的HTML内容

在进行代码编译前需要根据自己浏览器的版本,比如我的谷歌在搜索框输入:chrome://version/

出现:

Google Chrome 96.0.4664.93 (正式版本) (64 位) (cohort: Stable)

我的就是96的

下载地址:http://chromedriver./index.html

选择符合自己的版本和系统的压缩包,解压后放到项目文件目录下

第一步:获取网页HTML内容

需要导入的库:

from selenium import webdriver # 控制滚动条from time import sleep # 时间控制from bs4 import BeautifulSoup # 网页解析 获取数据

代码

# 获取网页HTML内容def gethtml(url):driver = webdriver.Chrome()# 初始化一个浏览器driver.maximize_window() # 设置窗口最大化driver.get(url) # 打开网页driver.refresh()# 刷新一下(如果不刷新,在下面循环的时候到最底下就会直接跳出)temp_h = 0 # 设置一个高度为 0js = "var q=document.documentElement.scrollTop=100000"driver.execute_script(js) # 执行上一行的js语句,直接将滚动条下拉到最底下sleep(3) # 等待三秒,向远程count = 100while count > 0:# 这里设置的循环一百次,想爬取完全可以改为Truecount -= 1driver.execute_script("window.scrollBy(0,4000)") # 循环向下拉去4000个单位,可以按照自己的速度设置快慢sleep(3)check_h = driver.execute_script("return document.documentElement.scrollTop;") # 获取当前滑动条的位置if check_h == temp_h:sleep(3) # 如果相等,等待3秒网速加载check_h = driver.execute_script("return document.documentElement.scrollTop;")if check_h == temp_h:break # 如果还相等,说明滑动条已经跳到下,评论全部加载完成,跳出循环temp_h = check_h # 将获取的高度设置为初始高度html = BeautifulSoup(driver.page_source, features="html.parser") # 使用解析器,解析获取的HTML内容driver.close()# 关闭浏览器return html

第二步:解析内容

需要导入的库:

import jieba # 分解词汇import re # 正则表达式 进行文件匹配import os # 创建目录import requests # 下载图片

代码:

# 解析网页数据def getData(baseurl, headers):findAgree = pile(r'<button class="Button Button--plain" type="button">(.*?) 人赞同了该回答</button>')# 查找点赞人数的正则表达式findContent = pile(r'<p data-pid=".*?">(.*?)</p>|<img class="origin_image zh-lightbox-thumb lazy" data-actualsrc="(.*?)"', re.S)# 查找item文本内容和图片,里面的超链接,代码,和列表等内容也可以创建正则表达式筛选出来,我就没写了data = []# 用来存所有解析好的数据html = gethtml(baseurl) # 调用获取上一步获取html代码的函数if os.path.exists("image"):shutil.rmtree("image")os.mkdir("image") # 创建一个image文件夹,存爬取的图片,如果已经存在,就删除for item in html.find_all('div', class_="List-item"): # 解析每一条,div里面class="List-item"的数据datalist = [] # 用来存每一条解析完的数据item = str(item)# 将item改为字符串格式agree = re.findall(findAgree, item)# 点赞人数更改格式if not agree: # 如果点赞人数列表为空就跳出(那是因为我爬取了几次发现最后一次的点赞人数都为空,会报错)breaktemp = agree[0].replace(",", "") # 去掉数字里面的","if int(temp) < 5:continue # 点赞数小于5 表示不是我们感兴趣的数据content = re.findall(findContent, item) # 用正则表达式查找所有内容stxt = "" # 用来存查找关键字的文本image = [] # 用来存需要爬取的图片的urlnewcontent = ""# 用来存添加了HTML标签、最后可以直接展示出来的内容for i, j in content:if i == '':if j == "": # 有可能图片也会存在为空的情况,要排除continueimage.append(j) # 如果content里面的第一项为空,那就说明这次是取到的图片url,具体content的样式自己可以输出来看一看,就明白了newcontent += '<img src="static/image/' + j[26:57] + '.jpg"/><br/>' # 给本地的图片 添加HTML标签:src路径 + 在本地保存的图片名else: # 下面就是content里面取到的文本内容if i.find("<a class=") == -1: # 查找超链接标签,没找到i = re.sub(r'<img alt=.*?/>', '', i) # 去掉知乎的样式图片stxt += i# 将取出来的文本加入stxt中,用来取出关键字i = i + '<br/>' # 加上换行标签else: # 找到了超链接标签i = re.sub(r'<span><a class=.*?target="_blank">', '', i)i = re.sub(r'<svg class=.*?</a></span>', '', i)i = re.sub(r'<a class=.*?</a>', '', i) # 去掉所有超链接内容i = re.sub(r'<img alt=.*?/>', '', i)stxt += ii = i + '<br/>'newcontent += i # 将取到的内容放到新的内容中kword = findkword(stxt) # 查找关键字if kword == 0: # 返回0 不存储continuedatalist.append(temp) # 1、存点赞数datalist.append(kword)# 2、存关键字datalist.append(newcontent)# 3、存总文本print("爬取图片中...")# 下载图片for i in image:path = "image/" + i[26:57] + ".jpg" # 下载到本地的路径while True:try:req = requests.get(i, headers=headers, stream=True, timeout=3) # 向图片的url请求break# 一直死循环爬取,爬取不到不出循环,并不是每次都能爬取成功except requests.exceptions.RequestException as e:continuewith open(path, "wb") as f: # 打开文件,保存图片到本地f.write(req.content)print("爬取图片完毕")data.append(datalist) # 添加到需要返回的列表中return data

查找关键字的函数:

# 查找关键字def findkword(stxt):excludes = ["用户", "可以", "我们", "这个", "一个", "于是", "大家", "这些", "--------", "-------------------", "---------", "span", "div", "class", "id"]# 一些不属于我们需要的内容的词kw = jieba.cut(stxt)# jieba拆分字符串d = {} # 空字典,用来存关键字和关键字出现的次数for i in kw:if len(i) == 1 or i in excludes: # 去掉我们不需要的词continued[i] = d.get(i, 0) + 1 # 关键字次数加一newd = sorted(d.items(), key=lambda x: x[1], reverse=True) # 按出现的次数排序count = 10# 这里我们取出现次数最多的前十个temp = ""if len(newd) < count: # 如果关键字小于我们需要的关键字个数,说明就不是我们想要的数据,就结束,放弃储存return 0for i in newd:temp += i[0] # 将关键字加到我们返回的temp中if count == 0:breaktemp += "、" # 关键字之间用"、"分割count -= 1return temp

第三步:将得到的数据保存在excel中

导入库:

import xlwt # 进行excel操作

代码:

def saveData(data, savepath):if os.path.exists(savepath):os.remove(savepath) # 判断excel的路径是否存在,存在就删除print("保存数据到excel")book = xlwt.Workbook(encoding="utf-8")# 初始化一个excel对象,编码格式为utf-8sheet = book.add_sheet("知乎评论内容", cell_overwrite_ok=True) # 向对象中添加一张sheet,更新是覆盖以前单元的数据col = ("点赞数", "关键字", "内容")for i in range(0, 3):sheet.write(0, i, col[i])# 先写入一行 标题for i in range(len(data)):for j in range(len(data[i])):sheet.write(i+1, j, data[i][j])# 依次每个位置写入数据book.save(savepath)# 保存excel

第四步:保存在数据库中

导入库:

import sqlite3 # 进行SQLITE数据库操作

代码:

#保存数据到数据库def saveDataDB(data, savepathdb):if os.path.exists(savepathdb):os.remove(savepathdb) # 判断数据库是否存在,存在就删除init_db(savepathdb)# 创建数据库和数据表print("保存数据到数据库")conn = sqlite3.connect(savepathdb)# 连接到数据库cur = conn.cursor()# 获取数据库游标for d in data:d[2] = d[2].replace("'", "''")# 将数据中的一个单引号变为两个单引号,SQLITE数据库的单引号转义方式for i in range(len(d)):d[i] = "'"+d[i]+"'" # 给每个数据两边加上单引号,方便执行sql语句插入sql = '''insert into python(agree,keyword,content)values(%s)'''%",".join(d) # 插入数据,使用","将d链表里面的数据链接起来cur.execute(sql)mit() # 如果不执行这个语句,数据的增加修改不会真的提交到数据库cur.close() # 关闭游标conn.close() # 关闭连接

创建数据库:

#创建数据库def init_db(savepathdb):sql = '''create table python(id integer primary key autoincrement,agree numeric ,keyword text, content text);'''# 创建表的sql语句conn = sqlite3.connect(savepathdb) # 连接数据库,如果数据库不存在则创建一个数据库cursor = conn.cursor()cursor.execute(sql) mit()conn.close()

第五步:主函数调用

def main():baseurl = "/question/27621722" # 网页urlheaders = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"} # 添加headers头,爬取图片的时候使用data = getData(baseurl, headers) # 得到数据savepath = "有趣的python.xls" # excel路径savepathdb = "python.db" # 数据库路径saveData(data, savepath) # 保存数据到excel表saveDataDB(data, savepathdb)# 保存数据到数据库print("爬取成功")

数据的爬取与存储就搞定了

excel:

数据库:

接下来我们做了一点数据的可视化:使用flask框架

第一步:创建主页

导入库

from flask import Flask, render_template, requestimport sqlite3

主要代码:

@app.route('/')def index():conn = sqlite3.connect("python.db") # 连接数据库cur = conn.cursor()sql = "select id,agree,keyword from python order by agree desc" data = cur.execute(sql) # 查找数据并点赞数排序newdate = []count = 0for i in data:count += 1 newdate.append(i+(count,)) # 添加一个名次return render_template("index.html", datalist=newdate) # 跳转到index.html界面,传递一个datalist参数

index.html代码:

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>有趣的python</title></head><body><table border="1"><tr><td>排名</td><td>关键字</td><td>点赞数</td><td>操作</td></tr>{% for data in datalist %}<tr><td>{{ data[3] }}</td><td>{{ data[2] }}</td><td>{{ data[1] }}</td><td><a href="/look?id={{ data[0] }}">查看</a></td> </tr>{% endfor %}</table></body></html>

运行完效果:

接着查看页面:

@app.route('/look',methods = ['POST', 'GET']) # 添加post、get方法def look():id = request.args.get('id')# 获取index.html页面传过来的idconn = sqlite3.connect("python.db")cur = conn.cursor()sql = "select content from python where id = {}".format(id)content = cur.execute(sql)# 查找文本for i in content:newcontent = i return render_template("look.html", content=newcontent[0]) # 将文本传到look.html页面

look.html:

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>查看</title></head><body><p>{{ content | safe }}</p># 将传过来的文本转义后输出</body></html>

效果:

项目到此还没结束

我们在index界面添加一个url的输入框

index.html添加以下代码:

<form action = "" method="post" ><p>请输入一个知乎网址</p><input type="text" name="url"><input type="submit" name="submit" value="开始爬取"></form>

再将爬取数据的代码放入flask框架中,用main函数调用一下

将图片保存的路径修改一下

这样我们的项目就已经完成了,可以实现爬取任何知乎网页数据,只需要你提交一个知乎url

总结:

不会的要学会查阅资料,总有解决办法。我只爬取了文本和图片,超链接和代码也可以根据HTML进行正则表达式摘取,还可以判断是否是知乎网址,还有数据分析,可以制作词云等比较直观的方式,页面也可以美化,但没必要。虽然代码短,但是花费的时间一点都不短。才学疏浅,有什么问题或者能改的可以求大佬给点建议。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。