Python豆瓣电影评论的爬取及词云显示
课程设计论文链接前言开发工具、核心库系统相关技术介绍系统分析与设计系统功能模块组成实现功能和目标爬取模块设计爬取过程中下一页的处理窗口界面设计系统实现爬取电影信息模块实现爬取评论实现词云模块实现系统开发总结全部代码附录课程设计论文链接
课程设计论文链接: /download/QQwli/14066030
前言
小白简单的课程设计,功能简单。
本文通过利用 Python 爬虫分类中的聚焦型爬虫网络系统以及python窗体的相关应用,在指定的网页下抓取相关的信息。在本文的实验中通过在电脑网页抓取豆瓣网中排名top250电影的影评信息,再通过选取要爬取的电影爬取电影评论,成功的爬取后在窗体中显示并以.csv的格式保存到本地,接着利用 jieba 分词对下载好的影评信息进行过滤筛选,将高频率出现的词语通过影评词云图的形式展现在面前。这样的爬取信息大大的提高了爬取信息的准确性,提高了资源的利用率,节约了查找信息的时间,真正的实现了有目的性的抓取信息。并且以窗体的形式展示更加具有可用性、易操作性。
开发工具、核心库
import requestsfrom lxml import etreeimport tkinterfrom wordcloud import WordCloudimport matplotlib.pyplot as pltimport jiebaimport threading
系统相关技术介绍
requests库
Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库。它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTTP 测试需求。Requests 的哲学是以 PEP 20 的习语为中心开发的,所以它比 urllib 更加 Pythoner。Requests中get请求是常用的请求之一,相对于post请求简单些,对于传参数的get请求有的还是有难度的。使用requests方法后,会返回一个response对象,其存储了服务器响应的内容,对已经提到的内容获取文本方式的响应体实例:当访问时,会使用其响应的文本编码进行解码,并且可以修改其编码使其自定义的编码进行解码。
系统分析与设计
系统功能模块组成
实现功能和目标
1.爬取豆瓣top250的电影名称和每部电影的链接。
2.保存top250.csv电影信息。
3.输入要爬取的电影名称,爬取前20页的影评信息。
4.保存’电影名称’.csv影评信息。
5.词云展示影评信息关键词。
爬取模块设计
打开豆瓣电影top250所在的网页;在浏览器上打开源代码页面,找到电影信息的源代码,在div class=”hd”,下找到电影详细链接所在的目录a用@href获取中间内容,即为该电影链接,在其包含的下一目录的第一个span中获取电影名称。获取结果如下所示:
需要提取的数据包括(可以使用 xpath 进行匹配):
详细链接:html.xpath(’//div[@class=“hd”]/a/@href’)
电影名称:html.xpath(’//div[@class=“hd”]/a/span[1]/text()’)
电影评论:html_elem.xpath(’//div[@class=“comment”]/p/span[1]/text()’)
爬取过程中下一页的处理
首先使用 Chrome 浏览器打开 豆瓣电影 Top250,很容易可以判断出网站是一个静态网页然后分析网站的 URL 规律,以便于通过构造 URL 获取网站中所有网页的内容:
首页:/top250
第二页:/top250?start=25&filter=
第三页:/top250?start=50&filter=
经过验证,很容易可以发现首页的 URL 也满足上面的规律。
窗口界面设计
系统实现
爬取电影信息模块实现
核心实现代码:
#解析、爬取电影。爬取电影信息,包括电影名字和连接def parse_pagemov(html):html_elem = etree.HTML(html)links = html_elem.xpath('//div[@class="hd"]/a/@href')#电影连接titles = html_elem.xpath('//div[@class="hd"]/a/span[1]/text()')#名字data = zip(links,titles)return datadef crawlmov():try:scr.insert(INSERT, '开始爬取电影信息....\n')url = '/top250?start={page}&filter='fd = open('MovieTop250.csv', 'w', encoding='utf-8', newline='')print('开始爬取')for page in range(0,250,25):scr.insert(INSERT,'正在爬取第 ' + str(page+1) + ' 页至第 ' + str(page+25) + ' 页......\n')html = get_page(url.format(page=str(page)))data = parse_pagemov(html)save2file(fd,data)fd.close()print('电影TOP250爬取结束')scr.insert(INSERT,'电影TOP250爬取结束,文件保存成功\n')except EXCEPTION as ex:scr.insert(INSERT, '爬取电影信息错误!\n')tkinter.messagebox.showerror(title='Hi', message=ex)#多线程爬取电影信息,防止页面卡死def thcrawmv():sart=time.time()p=threading.Thread(target=crawlmov)p.start()stop=time.time()
爬取评论实现
核心实现代码:
#封装def get_page1(url):#头部headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36'}response=requests.get(url=url,headers=headers)txt=response.textreturn txt#爬取电影评论内容def crawlcom(k,i):try:scr.insert(INSERT, '开始爬取评论信息....\n')url_base=i+'comments?limit=20&status=P&sort=new_score'fd = open('{}.csv'.format(k), 'w', encoding='utf-8', newline='')print("开始爬取")for page in range(0,200,20):scr.insert(INSERT,'正在爬取第 ' + str(page+1) + ' 条至第 ' + str(page+20) + ' 条评论'+'\n')if page<20:txt = get_page1(url_base)else:txt=get_page1(url.format(page=page))data = par_pagecom(txt)save2file(fd, data)time.sleep(random.random())url = i+'comments?start={page}&limit=20&status=P&sort=new_score'fd.close()tkinter.messagebox.showinfo(title='Hi', message='{}评论爬取结束,文件保存成功'.format(k))show(k)scr.insert(INSERT,"{}评论爬取结束,文件保存成功.\n".format(k))print("{}评论爬取结束".format(k))except EXCEPTION as ex:scr.insert(INSERT, '爬取电影评论错误!\n')tkinter.messagebox.showerror(title='Hi', message=ex)#多线程def thcrawcom():start=time.time()p=threading.Thread(target=crawlcom ,args=(En.get(),seach(En.get())))p.start()stop=time.time()#根据电影名字获取该电影的详细连接def seach(k):with open('MovieTop250.csv', encoding='utf-8') as f:data_list = [i for i in csv.reader(f)]dict = {}for i in data_list:dict[i[1]] = i[0]return dict.get(k)
词云模块实现
核心实现代码:
#生成词云并保存图片def wordcd(c):try:scr.insert(INSERT, "{}词云开始生成\n".format(c))path_txt = '{}.csv'.format(c)f = open(path_txt, 'r', encoding='UTF-8').read()#屏蔽出现率高的无用词汇,提高精准度stop = {'的', '我', '我们', '你们', '他们', '它', '她', '他', '你', '她们', '电影', '是', '还是','了', '就', '也','和', '看','一个','在','都','不','有','没有','那','那个','这','这个','啊','又'}cut_txt = " ".join(jieba.cut(f))wordcloud = WordCloud(font_path="C:/Windows/Font/simfang.ttf", background_color="white", width=1000,height=900,stopwords=stop).generate(cut_txt)plt.imshow(wordcloud, interpolation="bilinear")plt.axis("off")plt.show()wordcloud.to_file('{}.jpg'.format(c))except:tkinter.messagebox.showerror(title='Hi', message='生成词云出错')
系统开发总结
在对电影和评论爬取过程中,为了更能简化操作,本文特意增加了窗口显示界面,然而在增加了窗体后,也遇到了很多麻烦,在电影信息和评论爬取的时候,会有卡屏未响应情况,为了解决这个问题,通过查阅资料,发现是爬取过程中占用了开发工具的cpu,为此添加了多线程,顺利的解决了该问题。再者是按钮控件绑定有参数函数的时候,需要传递参数,但一直未能传递成功,后来查阅资料才知道需要用到lambda表达式来传递参数。
当然,因为自己的能力有限,程序也存在一些问题,比如程序未能连入数据库保存文件;实现过程较冗余复杂;窗口界面太简陋;实现的功能较少。
全部代码附录
import requestsfrom lxml import etreeimport jsonimport csvimport timeimport randomimport tkinterimport csvimport timefrom tkinter import *from tkinter import messageboxfrom tkinter import scrolledtextfrom tkinter import ttkfrom wordcloud import WordCloudimport matplotlib.pyplot as pltimport jiebaimport threading# 获取网页源代码,封装电影界面def get_page(url):headers = {'USER-AGENT':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}response = requests.get(url=url,headers=headers)html = response.textreturn html#封装def get_page1(url):#头部headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36'}response=requests.get(url=url,headers=headers)txt=response.textreturn txt#解析、爬取电影def parse_pagemov(html):html_elem = etree.HTML(html)links = html_elem.xpath('//div[@class="hd"]/a/@href')#电影连接titles = html_elem.xpath('//div[@class="hd"]/a/span[1]/text()')#名字data = zip(links,titles)return data#解析、爬取评论def par_pagecom(txt):txt_elem = etree.HTML(txt)name = txt_elem.xpath('//div[@class="comment"]/p/span[1]/text()')#评论data = zip(name)return data#写入保存文件def save2file(fd,data):writer = csv.writer(fd)for item in data:writer.writerow(item)#爬取电影信息,包括电影名字和连接def crawlmov():try:scr.insert(INSERT, '开始爬取电影信息....\n')#tkinter.messagebox.showinfo(title='Hi', message='正在爬取电影信息,大约5s')url = '/top250?start={page}&filter='fd = open('MovieTop250.csv', 'w', encoding='utf-8', newline='')print('开始爬取')for page in range(0,250,25):scr.insert(INSERT,'正在爬取第 ' + str(page+1) + ' 页至第 ' + str(page+25) + ' 页......\n')html = get_page(url.format(page=str(page)))data = parse_pagemov(html)save2file(fd,data)fd.close()print('电影TOP250爬取结束')scr.insert(INSERT,'电影TOP250爬取结束,文件保存成功\n')#tkinter.messagebox.showinfo(title='Hi', message='爬取结束,文件保存成功')except EXCEPTION as ex:scr.insert(INSERT, '爬取电影信息错误!\n')tkinter.messagebox.showerror(title='Hi', message=ex)#多线程爬取电影信息,防止页面卡死def thcrawmv():sart=time.time()p=threading.Thread(target=crawlmov)p.start()stop=time.time()#爬取电影评论内容def crawlcom(k,i):try:scr.insert(INSERT, '开始爬取评论信息....\n')url_base=i+'comments?limit=20&status=P&sort=new_score'fd = open('{}.csv'.format(k), 'w', encoding='utf-8', newline='')print("开始爬取")for page in range(0,200,20):scr.insert(INSERT,'正在爬取第 ' + str(page+1) + ' 条至第 ' + str(page+20) + ' 条评论'+'\n')if page<20:txt = get_page1(url_base)else:txt=get_page1(url.format(page=page))data = par_pagecom(txt)save2file(fd, data)time.sleep(random.random())url = i+'comments?start={page}&limit=20&status=P&sort=new_score'fd.close()tkinter.messagebox.showinfo(title='Hi', message='{}评论爬取结束,文件保存成功'.format(k))show(k)scr.insert(INSERT,"{}评论爬取结束,文件保存成功.\n".format(k))print("{}评论爬取结束".format(k))except EXCEPTION as ex:scr.insert(INSERT, '爬取电影评论错误!\n')tkinter.messagebox.showerror(title='Hi', message=ex)#多线程爬取电影评论def thcrawcom():start=time.time()p=threading.Thread(target=crawlcom ,args=(En.get(),seach(En.get())))p.start()stop=time.time()#根据电影名字获取该电影的详细连接def seach(k):with open('MovieTop250.csv', encoding='utf-8') as f:data_list = [i for i in csv.reader(f)]dict = {}for i in data_list:dict[i[1]] = i[0]return dict.get(k)#窗体展示电影信息和评论内容def show(k):#显示评论窗体master=tkinter.Tk()master.geometry('400x400')scr = scrolledtext.ScrolledText(master,width=90,height=80)scr.pack()if k==1:master.title('电影显示')with open('MovieTop250.csv', encoding='utf-8') as fp:data_list = [i for i in csv.reader(fp)]for item in data_list:scr.insert(15000.0,item[1]+'\n')else:master.title('{}评论显示'.format(k))with open('{}.csv'.format(k), encoding='utf-8') as fp:data_list = [i for i in csv.reader(fp)]for item in data_list:scr.insert(15000.0,item[0]+'\n')master.mainloop()#生成词云并保存图片def wordcd(c):try:scr.insert(INSERT, "{}词云开始生成\n".format(c))path_txt = '{}.csv'.format(c)f = open(path_txt, 'r', encoding='UTF-8').read()#屏蔽出现率高的无用词汇,提高精准度stop = {'的', '我', '我们', '你们', '他们', '它', '她', '他', '你', '她们', '电影', '是', '还是','了', '就', '也','和', '看','一个','在','都','不','有','没有','那','那个','这','这个','啊','又'}cut_txt = " ".join(jieba.cut(f))wordcloud = WordCloud(font_path="C:/Windows/Font/simfang.ttf", background_color="white", width=1000,height=900,stopwords=stop).generate(cut_txt)plt.imshow(wordcloud, interpolation="bilinear")plt.axis("off")plt.show()wordcloud.to_file('{}.jpg'.format(c))except:tkinter.messagebox.showerror(title='Hi', message='生成词云出错')#主函数if __name__=='__main__':try:#窗口布局window = tkinter.Tk()window.title('爬取电影评论')window.geometry('400x450')btn1 = tkinter.Button(window, text='爬取电影信息', font=('Arial', 11), width=10, height=1, command=thcrawmv)btn1.place(x=155,y=10)btn2 = tkinter.Button(window, text='显示电影信息', font=('Arial', 11), width=10, height=1, command=lambda :show(1))btn2.place(x=155,y=50)l=tkinter.Label(window, text='输入要查询的电影:', font=('Arial', 11), width=30, height=2)l.place(x=85,y=80)En=tkinter.Entry(window,width=15)En.place(x=155,y=115)btn3 = tkinter.Button(window, text='爬取', font=('Arial', 12), width=13, height=1,command=thcrawcom)btn3.place(x=50,y=150)btn4 = tkinter.Button(window, text='生成词云并保存', font=('Arial', 12), width=13, height=1,command=lambda: wordcd(En.get()))btn4.place(x=240,y=150)#window.geometry('600x600')scr = scrolledtext.ScrolledText(window,width=54,height=18)scr.place(y=200)window.mainloop()except:tkinter.messagebox.showerror(title='Hi', message='出错了!')