Python豆瓣电影评论的爬取及词云显示

  • 课程设计论文链接
  • 前言
  • 开发工具、核心库
  • 系统相关技术介绍
  • 系统分析与设计
  • 系统功能模块组成
  • 实现功能和目标
  • 爬取模块设计
  • 爬取过程中下一页的处理
  • 窗口界面设计
  • 系统实现
  • 爬取电影信息模块实现
  • 爬取评论实现
  • 词云模块实现
  • 系统开发总结
  • 全部代码附录


课程设计论文链接

课程设计论文链接:

前言

小白简单的课程设计,功能简单。
本文通过利用 Python 爬虫分类中的聚焦型爬虫网络系统以及python窗体的相关应用,在指定的网页下抓取相关的信息。在本文的实验中通过在电脑网页抓取豆瓣网中排名top250电影的影评信息,再通过选取要爬取的电影爬取电影评论,成功的爬取后在窗体中显示并以.csv的格式保存到本地,接着利用 jieba 分词对下载好的影评信息进行过滤筛选,将高频率出现的词语通过影评词云图的形式展现在面前。这样的爬取信息大大的提高了爬取信息的准确性,提高了资源的利用率,节约了查找信息的时间,真正的实现了有目的性的抓取信息。并且以窗体的形式展示更加具有可用性、易操作性。

开发工具、核心库

import requests
from lxml import etree
import tkinter
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import jieba
import threading

系统相关技术介绍

requests库
Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库。它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTTP 测试需求。Requests 的哲学是以 PEP 20 的习语为中心开发的,所以它比 urllib 更加 Pythoner。Requests中get请求是常用的请求之一,相对于post请求简单些,对于传参数的get请求有的还是有难度的。使用requests方法后,会返回一个response对象,其存储了服务器响应的内容,对已经提到的内容获取文本方式的响应体实例:当访问时,会使用其响应的文本编码进行解码,并且可以修改其编码使其自定义的编码进行解码。

系统分析与设计

系统功能模块组成

Python电影影评分析 python电影评论数据分析论文_词云

实现功能和目标

1.爬取豆瓣top250的电影名称和每部电影的链接。
2.保存top250.csv电影信息。
3.输入要爬取的电影名称,爬取前20页的影评信息。
4.保存’电影名称’.csv影评信息。
5.词云展示影评信息关键词。

爬取模块设计

Python电影影评分析 python电影评论数据分析论文_爬虫_02

打开豆瓣电影top250所在的网页;在浏览器上打开源代码页面,找到电影信息的源代码,在div class=”hd”,下找到电影详细链接所在的目录a用@href获取中间内容,即为该电影链接,在其包含的下一目录的第一个span中获取电影名称。获取结果如下所示:

需要提取的数据包括(可以使用 xpath 进行匹配):

详细链接:html.xpath(’//div[@class=“hd”]/a/@href’)

电影名称:html.xpath(’//div[@class=“hd”]/a/span[1]/text()’)

Python电影影评分析 python电影评论数据分析论文_Python电影影评分析_03


电影评论:html_elem.xpath(’//div[@class=“comment”]/p/span[1]/text()’)

爬取过程中下一页的处理

首先使用 Chrome 浏览器打开 豆瓣电影 Top250,很容易可以判断出网站是一个静态网页然后分析网站的 URL 规律,以便于通过构造 URL 获取网站中所有网页的内容:
首页:https://movie.douban.com/top250
第二页:https://movie.douban.com/top250?start=25&filter=
第三页:https://movie.douban.com/top250?start=50&filter=
经过验证,很容易可以发现首页的 URL 也满足上面的规律。

窗口界面设计

Python电影影评分析 python电影评论数据分析论文_html_04

系统实现

爬取电影信息模块实现

Python电影影评分析 python电影评论数据分析论文_Python电影影评分析_05

Python电影影评分析 python电影评论数据分析论文_python_06


核心实现代码:

#解析、爬取电影。爬取电影信息,包括电影名字和连接
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 crawlmov():
    try:
        scr.insert(INSERT, '开始爬取电影信息....\n')
        url = 'https://movie.douban.com/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()

爬取评论实现

Python电影影评分析 python电影评论数据分析论文_python_07


Python电影影评分析 python电影评论数据分析论文_python_08


核心实现代码:

#封装
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.text
    return 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)

词云模块实现

Python电影影评分析 python电影评论数据分析论文_爬虫_09


Python电影影评分析 python电影评论数据分析论文_爬虫_10


Python电影影评分析 python电影评论数据分析论文_python_11


核心实现代码:

#生成词云并保存图片
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 requests
from lxml import etree
import json
import csv
import time
import random
import tkinter
import csv
import time
from tkinter import *
from tkinter import messagebox
from tkinter import scrolledtext
from tkinter import ttk
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import jieba
import 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.text
    return 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.text
    return 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 = 'https://movie.douban.com/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='出错了!')