使用Python保存豆瓣《请回答1988》评论

使用Python保存豆瓣《请回答1988》评论

最近在B站“木鱼水心”up主的推荐下看了《请回答1988》这部韩剧,剧情虽然很普通平淡,但却很真实很贴近生活,确实是一部佳作,从豆瓣9.7分的评分上可以看出确实也得到了大多数人的认可(这里还包含了“狗善”党们大量的1分),今天我们就通过爬取这部剧在豆瓣上网友的评论方式学习一下python爬虫相关的知识。

百度百科:网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。

今天的知识点主要涉及两方面:

  • Python
    • requests库
    • openpyxl库
    • BeautifulSoup库

0、编程思路

  • 爬取数据
    • 编写爬虫函数
    • 解析评论中的信息,将昵称、评分、日期、评论保存至字典中,key为昵称,value为其余信息
    • 调用爬虫函数,爬取每一页评论,保存至excel和txt文件中

1、豆瓣评论web页面分析

首先我们分析一下页面的url网址,先看下前三页:

首页:https://movie.douban.com/subject/26302614/comments?status=P

第2页:https://movie.douban.com/subject/26302614/comments?start=20&limit=20&sort=new_score&status=P

第三页:https://movie.douban.com/subject/26302614/comments?start=40&limit=20&sort=new_score&status=P

根据前三页的url网址可以看到,除了首页之外,其余各页评论的url变化的只有“start”参数的值,每页显示的评论数量是20个,多看几页就会发现,后面的评论页面的url也都是这个规则,首页在尝试使用该规则构造的https://movie.douban.com/subject/26302614/comments?start=0&limit=20&sort=new_score&status=P访问后,发现response回的页面也是相同的,所以请求每页评论信息的方法就有了。

(1)打开网页,按F12打开“开发者工具”,刷新网页,在“开发者工具”的“Network”页签中可以查看到浏览器的全部请求,如下图:

(2)选择类型“Doc”,可以将需要的请求快速筛选出来,常见的网站页面信息请求的类型都是“Documents”,可以看到请求方法是“Get”,url的与上面我们分析的结果一致。

2、编写单一页面的爬虫函数测试

import requests

def get_page(url):
    headers = {
        'Cookie': 'bid=m7WfhBT77oo; __gads=ID=41045ba2fc768824:T=1560622066:S=ALNI_MaxeE94fpQh0nLuKMHCIBtaoceC4w; douban-fav-remind=1; gr_user_id=0ad82daf-1fc6-4713-9083-d8e60c2ffd58; _vwo_uuid_v2=DEFAFE0DC5E7106C89306EAF20C173CF7|e5bddad885499722f0997c6bbb30c987; ll="118123"; __yadk_uid=xQpScB6Xq2ewsbOFuFW3fBht8xRxDQ1H; viewed="30259573_26919485_26462816"; __utmz=30149280.1586195047.11.10.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; __utmz=223695111.1586195057.4.4.utmcsr=douban.com|utmccn=(referral)|utmcmd=referral|utmcct=/search; _pk_ref.100001.4cf6=%5B%22%22%2C%22%22%2C1586592906%2C%22https%3A%2F%2Fwww.douban.com%2Fsearch%3Fq%3D1988%22%5D; _pk_ses.100001.4cf6=*; ap_v=0,6.0; __utma=30149280.21987564.1560622068.1586195047.1586592906.12; __utmc=30149280; __utma=223695111.1336825842.1580544243.1586195057.1586592906.5; __utmb=223695111.0.10.1586592906; __utmc=223695111; _pk_id.100001.4cf6=79092dade13dacf0.1580544243.5.1586596820.1586195673.; __utmt=1; __utmb=30149280.3.8.1586597904490',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36'
        }
    try:
        res = requests.get(url, headers=headers)
        res.raise_for_status()
        return res.text
    except:
        return ""


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

html = get_page(url)
print(html)

打印的html回显正是评论web的源代码,说明单页爬虫函数正常。

3、获取评论中的信息

这里利用上文获取的html信息作为输入,BeautifulSoup库使用解析html信息,获取昵称、日期、评分和评论,BeautifulSoup的具体使用方法可以参考官网。

from bs4 import BeautifulSoup
import bs4
import re

html = get_page(url)

def get_data(data, html):
    soup = BeautifulSoup(html, 'lxml')
    divs = soup.find_all('div', attrs={'class': 'comment-item'})
    for div in divs:
        if isinstance(div, bs4.element.Tag):
            nickname = div.find('a', attrs={'title': True}).get('title')
            StarandDate = div.find_all('span', attrs={'title': True})
            if len(StarandDate) == 2:
                star = float(re.findall('allstar(\d\d).*?', str(StarandDate[0]))[0]) / 10
                date = StarandDate[1].get('title')
            else:
                star = "无"
                date = StarandDate[0].get('title')
            comment = div.find('span', attrs={'class': 'short'}).string.strip()
            data[nickname] = [date, star, comment]

data = {}
get_data(data, html)
print(data)

评分在网页上显示的是“力荐”“推荐”等,但是在源码中是可以看到实际的评分的,“allstar40 rating”中的“40”除以10就是实际的“4星”,如下图:

首页保存的字典data部分结果如下:

{'Dasiy': ['2016-02-11 22:54:52', 5.0, '看评论,大家都压正八,可是我喜欢崔泽啊,崔泽啊。'],
 '你与': ['2015-11-08 18:12:10',
  5.0,
  '才看两集我就敢打五星就是这么自信!!!回忆崔泽童年那段哗哗哭,想起了一起玩耍的小伙伴。看完结局的我只能说。。。编剧答应我们,以后不要再写爱情戏了ok?']}

4、循环前11页评论,将结果写入Excel和txt文件中

因为没有登录的情况下,最多只能访问前11页评论,所以这里我们只取前11页的热评。

整合前面的全部代码,第一部分的完整代码如下:

# -*- coding: utf-8 -*-
"""
Created on Sat Apr 11 17:07:45 2020

@author: F_numen
"""

import requests
from bs4 import BeautifulSoup
import bs4
import re
from openpyxl import Workbook


def get_page(url):
    # 写入请求头信息,防止被反爬虫
    headers = {
        'Cookie': 'bid=m7WfhBT77oo; __gads=ID=41045ba2fc768824:T=1560622066:S=ALNI_MaxeE94fpQh0nLuKMHCIBtaoceC4w; douban-fav-remind=1; gr_user_id=0ad82daf-1fc6-4713-9083-d8e60c2ffd58; _vwo_uuid_v2=DEFAFE0DC5E7106C89306EAF20C173CF7|e5bddad885499722f0997c6bbb30c987; ll="118123"; __yadk_uid=xQpScB6Xq2ewsbOFuFW3fBht8xRxDQ1H; viewed="30259573_26919485_26462816"; __utmz=30149280.1586195047.11.10.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; __utmz=223695111.1586195057.4.4.utmcsr=douban.com|utmccn=(referral)|utmcmd=referral|utmcct=/search; _pk_ref.100001.4cf6=%5B%22%22%2C%22%22%2C1586592906%2C%22https%3A%2F%2Fwww.douban.com%2Fsearch%3Fq%3D1988%22%5D; _pk_ses.100001.4cf6=*; ap_v=0,6.0; __utma=30149280.21987564.1560622068.1586195047.1586592906.12; __utmc=30149280; __utma=223695111.1336825842.1580544243.1586195057.1586592906.5; __utmb=223695111.0.10.1586592906; __utmc=223695111; _pk_id.100001.4cf6=79092dade13dacf0.1580544243.5.1586596820.1586195673.; __utmt=1; __utmb=30149280.3.8.1586597904490',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36'
        }

    # 使用requests库进行请求
    try:
        res = requests.get(url, headers=headers)
        res.raise_for_status()
        return res.text
    except:
        return ""


def get_data(data, html):
    soup = BeautifulSoup(html, 'lxml')
    # 筛选出全部评论“div”标签块,每个块中包含一条评论信息
    divs = soup.find_all('div', attrs={'class': 'comment-item'})

    # 循环获取每一条评论信息
    for div in divs:
        if isinstance(div, bs4.element.Tag):
            # 获取昵称
            nickname = div.find('a', attrs={'title': True}).get('title')

            # 获取评分和日期
            StarandDate = div.find_all('span', attrs={'title': True})
            if len(StarandDate) == 2:
                star = float(re.findall('allstar(\d\d).*?', str(StarandDate[0]))[0]) / 10
                date = StarandDate[1].get('title')
            else:
                star = "无"
                date = StarandDate[0].get('title')

            # 获取评论
            comment = div.find('span', attrs={'class': 'short'}).string.strip()

            # 将获取的信息写入data{}
            data[nickname] = [date, star, comment]


def write_excel(data):           
    # 创建Excel的工作簿并选择默认的sheet页
    wb = Workbook()
    ws = wb.active

    # 写入第一行表头 
    ws.append(['昵称', '日期', '评分', '评论'])

    # 将data{}信息写入Excel
    for key, value in data.items():
        ws.append([key, value[0], value[1], value[2]])

    # 保存Excel文件
    wb.save("reply1988评论.xlsx")

def comment_write_txt(data):
    # 因为有特殊字符,默认的gbk编码无法识别,所以使用utf-8编码  
    with open('comment.txt', 'a', encoding='utf-8') as f:

        # 循环写入data{}中的评论信息
        for key, value in data.items():
            f.write(value[2] + '\n')

if __name__ == '__main__':
    # 初始化data{}
    data = {}

    for i in range(11):
        # 生成本页url
        url = 'https://movie.douban.com/subject/26302614/comments?start=%s&limit=20&sort=new_score&status=P' % (20 * i)

        # 使用get_page函数获取本页html信息
        html = get_page(url)

        # 使用get_data函数解析html并将信息保存至data{}
        get_data(data, html)

    # 创建Excel,并将data{}信息写入Excel    
    write_excel(data)

    # 创建txt,并将data{}中的评论信息写入txt
    comment_write_txt(data) 

输出结果如下:


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 xumeng32@126.com

文章标题:使用Python保存豆瓣《请回答1988》评论

文章字数:2k

本文作者:F_numen

发布时间:2020-04-11, 16:22:33

最后更新:2020-04-11, 22:07:17

原始链接:https://netheroone.cn/archives/b411997.html

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
/*baidu统计*/