【Python爬虫入门】【数据分析】爬取豆瓣图书评论并生成词云图——以《三体》为例

导入必要的库

import requests  #用于爬取html
from bs4 import BeautifulSoup   #用于转换soup对象,方便处理
from wordcloud import WordCloud  #词云图
from collections import Counter  #计数工具
import heapq  #计数工具
import jieba.posseg as psg  #分词工具
import matplotlib.pyplot as plt  #显示词云图

查看网址、headers

  • 登录豆瓣图书网,打开任意图书短评,并登录
    在这里插入图片描述
  • 点击F12进入开发者模式,选择网络,刷新一下页面
    在这里插入图片描述
  • 查看cookie与User-Agent
    在这里插入图片描述
    在这里插入图片描述
  • 这样我们就可以定义我们的headers
    db_headers = {'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0"  \
            ,'cookie':'bid=uQtf0......27093'}
    
  • 查看前后页,发现网址中的start对应第几个评论开始,sort后对应按热度(score)还是按时间(time)排序(当然 subject 后的数字就对应哪本书了,修改此数字即可分析你感兴趣的书
    在这里插入图片描述
    不难想到利用format格式化表示网址
    f"https://book.douban.com/subject/2567698/comments/?start={i*20}&limit=20&status=P&sort=score"
    

获取评论

分析html结构,定义函数

在这里插入图片描述
在这里插入图片描述
可以看到评论列表位于 class_ 为 “comment-item” 的 div 标签下
继续查看 li 标签,发现评论在 class_ 为 “short” 的 span 标签下,调用 string 属性即可获取
在这里插入图片描述
在这里插入图片描述

def get_pg_html(url, head):
    """返回短评html"""
    try:
        r = requests.get(url, headers=head)
        r.raise_for_status()
        return r
    except:
        print(url+"抓取失败!")
        return None


def get_comments(html):
    """根据该页html返回该页评论列表"""
    soup = BeautifulSoup(html.text, 'html.parser')
    com_li_lst = soup.body.find_all(class_="comment-item")  #返回评论li列表
    return [li.find(class_="short").string for li in com_li_lst]  #返回评论内容

爬取评论

comments = []
for i in range(15):  #提取最热300条
    url = f"https://book.douban.com/subject/2567698/comments/?start={i*20}&limit=20&status=P&sort=score"
    html = get_pg_html(url, db_headers)
    comments.extend(get_comments(html))  #追加到列表
for i in range(5):  #提取最新100条
    url = f"https://book.douban.com/subject/2567698/comments/?start={i*20}&limit=20&status=P&sort=time"
    html = get_pg_html(url, db_headers)
    comments.extend(get_comments(html))  #追加到列表
print(len(comments))
comments[-20:]

out:

400
['物理的尽头是数学,数学的尽头是哲学,哲学的尽头是神学。',
 '三体的开头,铺垫得有点无聊,也可能是因为有点深奥吧,差点看不下去了,不过看了后面两本,觉得这一本的铺垫很重要。',
 '“也许,人类和邪恶的关系,就是大洋与漂浮于其上的冰山的关系,它们其实是同一种物质组成的巨大水体,冰山之所以被醒目地认出来,只是由于其形态不同而已,而它实质上只不过是这整个巨大水体中极小的一部分……人类真正的道德自觉是不可能的,就像他们不可能拔着自己的头发离开大地。要做到这一点,只有借助于人类之外的力量”。',
 '除了一两个闪光点,整体被虚吹神化到无以复加。Netflix的改编成就了这本庸作。',
 '谁懂啊我读完第一部真的以为自己看了1/3结果发现页数对不上…',
 '去魅了。在我这两星半,就算是陈述物理学天文学也不该是这么硬邦邦的枯燥,生活大爆炸每集都有物理学科普,虽然也无聊但不会让人想跳过,这里叙述太大片了,但批斗那里说的不错,三体人想象确实有创意,还差两篇结尾没看完',
 '大框架不错,冲着侦探部分去的,里面的物理理论完全没看懂😂',
 '相较于三本书,最喜欢第一本,徐徐道来的故事把人逐渐的引入科学,让物理小白也可以深陷其中。',
 '想象力还可以,主要在于物理知识。文笔很一般,毫无美感,对人物的刻画也干瘪,简直不如武侠小说。有点太宏观,忽视了个体人,纯写物理技术,没写出人的血肉。',
 '“在中国,任何超脱飞扬的思想都会砰然坠地的,现实的引力太沉重了。”\n相信在这种环境下,如果我是叶文洁,我也会发出那条信息。',
 '一分减在男凝',
 '想象力丰富得叹为观止',
 '慕名而来但是真觉得描写水平太差了 人文含量超低 说话土土的 故而多么厉害的设定在当下这个故事爆炸的时代 也都没什么了(纯个人感受)没有办法把一件事情写好 再厉害的世界观 上线也就到那了。',
 '补标',
 '感觉像维伦纽瓦沙丘1一样,整本书像是一个大型预告',
 '👍🏻',
 '看完剧补一下,只能说还行吧。网飞的改编帮忙提升了很多',
 '第二遍读了,真的很好',
 '相比起其他,三体一更像是一个巨大的背景介绍\n介绍三体的恶劣环境\n介绍三体前往地球的初衷\n介绍地球人即将面临的危机\n从“物理学不存在”到“智子锁死的科学”,再到“我们都是虫子”的认知\n开头的悬疑恐怖感挺足的\n眼前的倒计时让人身临其境地觉得可怕\nps.喜欢史强和叶文洁,不同类型的智慧人',
 '宇宙苍穹映射出人类的悲喜和无知,他们自以为是的以为,整个宇宙都在为他们闪耀。\n\n大刘的笔,大史的晚,淼淼的眼睛,叶文洁的超然,杨卫宁的牺牲,罗辑的天才脑袋…等等等等,谢谢你们在一段时间带我遨游宇宙,更深刻的看待人生起伏,学会变幻无常的道理。']

文本预处理

#文本预处理
rule = lambda s:len(set(s))/len(s)>0.5   #规则:重复字不超过一半
pure_comments = [c for c in filter(rule, comments)]  #提取有效评论
print(f"有效评论数:{len(pure_comments)}")
jieba_lst = []
sign = """!@#$%^&*()_+-=[]{};':",./<>?|\\:“”《》?【】;’、,。!…\n\t """
for comment in comments:
    for ch in sign:
        comment = comment.replace(ch,"")  #删去无用字符
    jieba_lst.extend(psg.lcut(comment))  #获取分词

out:

有效评论数:396
print(len(jieba_lst))
jieba_lst[:20]

out:

13730
[pair('一直', 'd'),
 pair('认为', 'v'),
 pair('写作', 'v'),
 pair('是', 'v'),
 pair('件', 'q'),
 pair('很', 'd'),
 pair('耗费', 'v'),
 pair('体力', 'n'),
 pair('与', 'p'),
 pair('脑力', 'n'),
 pair('的', 'uj'),
 pair('事情', 'n'),
 pair('特别', 'd'),
 pair('是从', 'v'),
 pair('新', 'a'),
 pair('构架', 'n'),
 pair('一个', 'm'),
 pair('新', 'a'),
 pair('的', 'uj'),
 pair('世界', 'n')]

关于 jieba 库的词性可参考以下文章:
Python——jieba优秀的中文分词库(基础知识+实例)
在这里插入图片描述
接下来选择我们需要的词,并大致查看出现次数

#提取关键词
vital_words = [w.word for w in jieba_lst if w.flag in ('a','i','l','n','nr','ns','nt','nz')]
text = " ".join(vital_words)  #组合

ndic = dict(Counter(vital_words))
heapq.nlargest(20, ndic.items(), key=lambda x:x[1])

out:

[('三体', 100),
 ('科幻', 95),
 ('人', 81),
 ('人类', 75),
 ('文笔', 66),
 ('文明', 63),
 ('大', 56),
 ('故事', 51),
 ('宇宙', 50),
 ('世界', 40),
 ('感觉', 39),
 ('人物', 39),
 ('好', 39),
 ('叶文洁', 39),
 ('小说', 38),
 ('作者', 37),
 ('物理', 33),
 ('中国', 32),
 ('想象力', 31),
 ('游戏', 29)]

生成词云图

#词云图
wc = WordCloud(width=600, height=600, max_font_size=150, min_font_size=5, max_words=40,background_color='white',\
               font_path=r"C:\Users\...\SmileySans-Oblique.ttf")  #创建词云对象
wc_img = wc.generate(text)
plt.imshow(wc_img)

out:

<matplotlib.image.AxesImage at 0x21ef0723fd0>

在这里插入图片描述
关于 WordCloud ,可以了解以下文章:
python词云 wordcloud库详细使用教程
wordcloud词云图美化

  • 25
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值