美文网首页
《解忧杂货店》豆瓣书评爬取和SnowNLP情感分析初探

《解忧杂货店》豆瓣书评爬取和SnowNLP情感分析初探

作者: f5065e26181b | 来源:发表于2018-10-10 13:12 被阅读219次

一、摘要

《解忧杂货店》原作名《 ナミヤ雑貨店の奇蹟》,是日本作家东野圭吾写作的长篇小说。2011年于《小说野性时代》连载,于2012年3月由角川书店出版,2014年5月,南海出版公司出版中文版,译者李盈春。该书讲述了在僻静街道旁的一家杂货店,只要写下烦恼投进店前门卷帘门的投信口,第二天就会在店后的牛奶箱里得到回答:因男友身患绝症,年轻女孩月兔在爱情与梦想间徘徊;松冈克郎为了音乐梦想离家漂泊,却在现实中寸步难行;少年浩介面临家庭巨变,挣扎在亲情与未来的迷茫中……他们将困惑写成信投进杂货店,奇妙的事情随即不断发生。同名华语电影于2017年上映。 2017年12月15日,亚马逊中国发布基于亚马逊阅读大数据产生的一系列年度阅读榜单。其中,东野圭吾的《解忧杂货店》连续4年上榜,又一次成为2017年亚马逊最畅销图书。

解忧杂货店.jpg
本人非常喜欢这部小说,在学Python过程中,使用requests+BeautifulSoup爬取了豆瓣网上该书书评,并通过借鉴如何用Python做舆情时间序列可视化?,基于用户评论的短文本情感分析模型设计两篇文章的思路,对书评进行了情感分析。

二、开发环境

版本:python3.5.2
编程软件:pycharm
配置库:

  1. pip install pyecharts
  2. pip install BeautifulSoup
  3. pip install requests
  4. pip install pymongo
  5. pip install snownlp
  6. pip install Pandas

三、爬虫设计与实现

爬虫思路很线性,获取网页链接,通过get_page()函数获取网页,返回页面信息,通过parse_one_page()函数进行解析获取信息,通过save_to_mongo()函数将数据存储至MongoDB数据库中。具体代码如下:

def get_page(url_base):
    print('正在读取页面……')
    ips = ['自己爬一些可用ip']
    proxy_ip = {'http':ips[random.randint(0, 9) ]}
    try:
        response = requests.get(url_base,proxies = proxy_ip)
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        return None
def parse_one_page(html1):
    soup = BeautifulSoup(html1, "html.parser")
    for item in soup.find_all(class_="comment-item"):
        comment_info = {
            'user_name': None,
            'user_url': None,
            # 'user_loc': None,
            'star': None,
            'time': None,
            'useful': None,
            'comment': None
        }
        try:
            comment_info['user_name'] = item.find(class_ ='avatar').find('a').get('title')
        except:
            pass
        try:
            comment_info['user_url'] = item.find(class_ ='avatar').find('a').get('href')
        except:
            pass
        try:
            tmp = item.find(class_="comment-info").find('span').get('title')
            if tmp == '力荐':
                comment_info['star'] = 5
            elif tmp == '推荐':
                comment_info['star'] = 4
            elif tmp == '还行':
                comment_info['star'] = 3
            elif tmp == '较差':
                comment_info['star'] = 2
            elif tmp == '很差':
                comment_info['star'] = 1
        except:
            pass
        try:
            if comment_info['star']==None:
                comment_info['time'] = item.find(class_="comment-info").find_all('span')[0].get_text().split('-')
            else:
                comment_info['time'] = item.find(class_="comment-info").find_all('span')[1].get_text().split('-')
        except:
            pass
        try:
            comment_info['useful'] = int(item.find(class_="vote-count").get_text())
        except:
            pass
        try:
            comment_info['comment'] = item.find(class_="short").get_text()
        except:
            pass
        save_to_mongo(comment_info)
def save_to_mongo(result):
    try:
        if db[MONGO_TABLE].insert(result):
            print('存储到MongoDB成功',result)
    except Exception:
        print('存储到MongoDB失败', result)
def main():
    url_base = 'https://book.douban.com/subject/25862578/comments/hot?'
    html = get_page(url_base)
    page_num = int(get_page_num(html))
    print(math.ceil(page_num / 20))
    for i in range(1,math.ceil(page_num/20)):
        url_tmp = url_base + "p=%s"%i
        html1 = get_page(url_tmp)
        time.sleep(4)
        try:
            parse_one_page(html1)
            print(i, '页正常')
        except:
            print(i,'页出错')

对于网页翻页,由于网页链接特点为 url_base = 'https://book.douban.com/subject/25862578/comments/hot?'shizip=num,多以获取总条数后除以每页评论量,得到总页数,进行循环。如图:

网页截图.PNG
def get_page_num(html):
    soup = BeautifulSoup(html, "html.parser")
    page_num = soup.find(id='total-comments').get_text().replace("全部共 ","").replace(" 条","")
    print(page_num)
    return page_num

在实际运行过程中出现了被反爬虫的情况,403:

服务器禁止提供服务.PNG
解决方案python爬虫防止IP被封的一些措施。主要采用:
1.构建代理池,每次发出请求,伪装一个ip,避免同一ip多次使用。https://github.com/Germey/ProxyPool使用Redis+Flask维护动态代理池,使用该项目爬取了一些免费网站上的ip,由于免费,可用的不多,凑合用(手动狗头)
response = requests.get(url_base,proxies = proxy_ip)

2.延长请求之间的时间,减小访问评率,也是笨办法。
最终获取数据如图:


爬取数据.PNG

四、SnowNLP书评情感分析

SnowNLP是基于中文文本的文本情感分析包,其训练数据就是评论数据,但是和书评差异还是很大的,此次只是尝试,比较浅显。从数据库中提取评论数输入模型中,得到评分结果。文章如何用Python做情感分析?有详细解释。

from snownlp import SnowNLP
def get_sentiment_cn(text):
    s = SnowNLP(text)
    return s.sentiments

模型输出结果与用户评星(1-5归一化)结果进行比较,截取了23组进行展示:

模型与用户打分对比.png
从结果看,大部分结果还是能反应用户评分的,也有不少错的比较离谱,这是因为训练数据与本文数据不是同一类型,要提高效率还得用此类数据进行训练(下次再做)。拿出具体数据看一下:
评分表.PNG
第14、22行评星很高但是模型给出的确实相反的结论,因为类似“泪目”“免疫”“”“睡着了”在snownlp 模型中属于比较消极的词汇,而评论的人要表达的意思却相反。第3、21条都是倾向很明显的词,所以结果正确,第24行是一个中性的评论,但由于“变态”的出现,模型判定为消极情感。
总而言之,此次试验能大概反应感情的倾向,但是离精确还差的很远。可以参考如何用Python和机器学习训练中文文本情感分类模型?

五、其他数据分析

选取了20000余组数据进行分析。
1.历年读者评论量


年度评价数量 (1).png

2.用户评价情况


读者打分.png
读者打分比例 (1).png

关注“1024程序开发者社区”,回复“解忧杂货店”,获取代码和更多资源!


关注我.jpg

相关文章

网友评论

      本文标题:《解忧杂货店》豆瓣书评爬取和SnowNLP情感分析初探

      本文链接:https://www.haomeiwen.com/subject/ovepaftx.html