Python步步飞升之爬取豆瓣电影短评告诉你《白蛇:缘起》为啥这么热

Python步步飞升之爬取豆瓣电影短评告诉你《白蛇:缘起》为啥这么热

白蛇:缘起头图.jpg

1. 前言

一直喜欢动画电影,国内国外都看了不少。很让人欣慰的是,国产动画大电影已经长进不少,《魁拔》系列,《大圣归来》,《大护法》等都让我眼前一亮,最近正在上映的《白蛇:缘起》为追光动画出品,之前该公司的《小门神》就让我高兴的紧。在观影之前先看豆瓣评论以避深坑已经成为习惯,加之最近词图分析也很有意思,作此文抛砖引玉。

2. 大概思路

  • 用BeautifulSoup从豆瓣电影上爬取短评保存文件中
  • 从文件中找出评论内容用jieba分词
  • 用在线可视化工具wordart生成热词图片

3. 从豆瓣电影上爬取短评

3.1 豆瓣网站爬虫限制

  • 多次尝试之后发现,不登录的情况下,只能查询到200条短评
  • 登录之后也只能查看500条短评
  • 从豆瓣网站robots.txt知道网站期望的被访问的间隔为5s
# Crawl-delay: 5

3.2 分析URL

刚开始进入短评url如下

https://movie.douban.com/subject/30331149/comments?start=0&limit=20&sort=new_score&status=P

查看源码搜索"后页"

<div id="paginator" class="center">
                <span class="first"><< 首页</span>
                <span class="prev">< 前页</span>
                <a href="?start=20&amp;limit=20&amp;sort=new_score&amp;status=P&amp;percent_type=" data-page="" class="next">后页 ></a>
        </div>

可以看到源码后页元素中有“start=20”,代码中获取这个start用以生成下一页待爬取url。
点击最下方“后页”按钮,新页面url如下

https://movie.douban.com/subject/30331149/comments?start=20&limit=20&sort=new_score&status=P

其中,30331149为《白蛇:缘起》电影id。每次下一页后,start+20,每页限制为20条数据。
因douban限制,短评最多能查看500条数据,所以进入url

https://movie.douban.com/subject/30331149/comments?start=480&limit=20&sort=new_score&status=P

之后发现“后页”按钮灰掉,已经不能再往下翻页了。
查看源码搜索"后页"

<div id="paginator" class="center">
                <a href="?start=0&amp;limit=20&amp;sort=new_score&amp;status=P&amp;percent_type=" data-page="1"><< 首页</a>
                <a href="?start=479&amp;limit=-20&amp;sort=new_score&amp;status=P&amp;percent_type=" data-page="">< 前页</a>
                <span class="next">后页 ></span>
        </div>

发现后页元素中start不存在,所以爬取的时候可以这点来判断是否结束爬取。

        each = 0
        while 1:
            url = 'https://movie.douban.com/subject/' + \
                self._movieId+'/comments?start=' + str(each) + \
                '&limit=20&sort=new_score&status=P'
            urlInfo = requests.get(
                url, cookies=self._cookies, headers=self._headers)
            print("从URL(%s)抓取评论中..." % urlInfo.url,)
            nextPage = self.crawlOnePage(urlInfo.text)
            # 没有下一页,最后一个元素为前页
            if int(nextPage[-1]) < each:
                print('抓取结束...')
                break
            else:
                time.sleep(round(random.uniform(5.0, 5.5), 2)) ## 随机暂停5-5.5s时间再发起请求
                each = int(nextPage[-1])

3.3 cookie模拟登录

最简单的方式就是在网站上登录之后,Chrome中“F12”快捷键点开调试工具,查看网络随意选取一个请求,记住header中cookie信息,爬取数据时添加到请求header。


login_get_cookie.png

用requests发送请求时,带上cookie就好

self._cookies = {'cookie': cookie}
urlInfo = requests.get(url, cookies=self._cookies, headers=self._headers)

3.4 分析评论页源码获取指定信息

查看一个评论页面的源代码


analyze_commentitem_source.png

可见,

  • 评论放在一个div中,id="comments"
  • 每个评论都在一个div中,class="comment-item"
  • 评论人名称在一个链接中,当href有值且链接中包含“people”元素,存在用户已注销情况
  • 评论时间在一个span中,class="comment-time "
  • 评论内容在一个span中,class="short"
  • 评论打星在一个span中,class="rating",存在未打分情况
  • 投票在一个span中,class="votes"

用BS可以轻松提取这些数据,代码如下

    def crawlOnePage(self, html):
        soup = BeautifulSoup(html, 'lxml')
        # 获取电影名称
        if self._movieName == '':
            self._movieName = soup.select(
                '.movie-summary')[0].find_all('img')[0]['title']

        for item in soup.select('.comment'):
            comment = {}
            # 评论者
            for a in item.find_all('a'):
                if 'people' in a['href']:
                    comment['user'] = a.string
            # 日期
            comment['date'] = item.select('.comment-time')[0].string.strip()
            # 内容
            comment['content'] = item.select('.short')[0].string
            # 评价
            try:
                comment['eval'] = item.select('.rating')[0]['title']
                # stars
                comment['star'] = item.select('.rating')[0]['class'][0][-2]
            except Exception:
                # 存在用户没有打星情况
                # print(str(item).encode('GBK', 'ignore').decode('GBk'))
                comment['eval'] = '未打星'
                comment['star'] = '-1'
            # votes
            comment['votes'] = item.select('.votes')[0].string

            self._comments.append(comment)

        pages = re.findall(r'href="\?start=(\d+)&.+"',
                           str(soup.select('#paginator')))
        return pages

4. 获取到的评论数据保存在csv中

使用csv模块可以很方便的保存文件

        fileName = self._movieName + '.csv'
        with open(fileName, 'w', encoding='utf-8-sig', newline='') as csvfile:
            fieldnames = ['user', 'date', 'eval', 'star', 'votes', 'content'] ## header
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
            writer.writeheader()
            [writer.writerow(comment) for comment in self._comments] ## save comments line by line

5. 评论内容分词

下载“中文停用词表.txt”,也可以在网上搜索相应资源
使用jieba分词取最热100词,并保存结果在文件中

    def fenci(self):
        print('开始分词...')
        fenciFileName = os.path.join(
            sys.path[0], self._movieName + '_分词结果.csv')
        CommentRecord = namedtuple(
            'CommentRecord', ['user', 'date', 'eval', 'star', 'votes', 'content'])

        analyse.set_stop_words(os.path.join(sys.path[0], '中文停用词表.txt'))
        content = []
        csvName = os.path.join(sys.path[0], self._movieName + '.csv')
        for emp in map(CommentRecord._make, csv.reader(open(csvName, mode='r', encoding='utf-8-sig'))):
            content.append(emp.content)

        tags = analyse.extract_tags(
            ' '.join(content), topK=100, withWeight=True)
        with open(fenciFileName, 'w', encoding='utf-8-sig', newline='') as csvfile:
            writer = csv.writer(csvfile)
            [writer.writerow(item[0] + '\t' + str(int(item[1] * 1000)))
             for item in tags]

        print('分词结束,保存结果在"%s"中...' % fenciFileName)

6. 用在线可视化工具wordart生成热词图片

网站地址在此wordart

6.1 导入生成的词汇

打开“白蛇:缘起_分词结果.csv”,复制两列所有数据。
如图,在网站中一次点击“WORDS”,“Import”,选中“CSV Fromat”选项,粘贴到文本框中,点击“Import Words”按钮。


wordart_import_words.png

6.2 选择SHAPES

这里就是选择形状图用来做背景,也可以自行上传图像文件

6.3 选择FONTS

网站本身不支持中文,需要上传一个中文字体,不然显示出来都是框框。这里我上传了NotoSansMonoCJKsc-Regular.otf用以显示。然后点击“Visualize”按钮即可生成词图。

wordart_import_choose_font_visu.png

6.4 生成的词图

白蛇:缘起.png

7. 结语

如有疑问,欢迎留言共同探讨。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容