├── webcrawling ├── result │ └── ciyun.png ├── background_love.jpg ├── __pycache__ │ ├── douban_wordcloud.cpython-36.pyc │ ├── douban_movie_comment.cpython-36.pyc │ ├── douban_score_analysis.cpython-36.pyc │ └── douban_sentiment_analysis.cpython-36.pyc ├── readme.md ├── douban_score_analysis.py ├── douban_wordcloud.py ├── main.py ├── douban_sentiment_analysis.py ├── douban_movie_comment.py └── hit_stopwords.txt └── README.md /webcrawling/result/ciyun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RonnieFu/Douban-movie-review-crawl-word-cloud/HEAD/webcrawling/result/ciyun.png -------------------------------------------------------------------------------- /webcrawling/background_love.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RonnieFu/Douban-movie-review-crawl-word-cloud/HEAD/webcrawling/background_love.jpg -------------------------------------------------------------------------------- /webcrawling/__pycache__/douban_wordcloud.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RonnieFu/Douban-movie-review-crawl-word-cloud/HEAD/webcrawling/__pycache__/douban_wordcloud.cpython-36.pyc -------------------------------------------------------------------------------- /webcrawling/__pycache__/douban_movie_comment.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RonnieFu/Douban-movie-review-crawl-word-cloud/HEAD/webcrawling/__pycache__/douban_movie_comment.cpython-36.pyc -------------------------------------------------------------------------------- /webcrawling/__pycache__/douban_score_analysis.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RonnieFu/Douban-movie-review-crawl-word-cloud/HEAD/webcrawling/__pycache__/douban_score_analysis.cpython-36.pyc -------------------------------------------------------------------------------- /webcrawling/__pycache__/douban_sentiment_analysis.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RonnieFu/Douban-movie-review-crawl-word-cloud/HEAD/webcrawling/__pycache__/douban_sentiment_analysis.cpython-36.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 豆瓣电影评论爬取+情感分析+词云 2 | 3 | 注意未登录的豆瓣账号(不填写Cookie,只能爬取200条评论,登陆后填写可以爬取500条) 4 | 5 | 运行该项目需要调整好main.py中的参数,直接运行即可 6 | 7 | ### 主要修改 8 | 9 | url_1中电影号修改为对应豆瓣中的电影号 10 | 11 | ![image-20210106194656245](https://i.loli.net/2021/01/06/icQvZnNy1zoHAdT.png) 12 | 13 | 加到应代码的url的subject后面数字位置即可 14 | 15 | ```python 16 | url_1 = "https://movie.douban.com/subject/27073752/comments?start=" 17 | ``` 18 | -------------------------------------------------------------------------------- /webcrawling/readme.md: -------------------------------------------------------------------------------- 1 | ## 豆瓣电影评论爬取+情感分析+词云 2 | 3 | 注意未登录的豆瓣账号(不填写Cookie,只能爬取200条评论,登陆后填写可以爬取500条) 4 | 5 | 运行该项目需要调整好main.py中的参数,直接运行即可 6 | 7 | ### 主要修改 8 | 9 | url_1中电影号修改为对应豆瓣中的电影号 10 | 11 | ![image-20210106194656245](https://i.loli.net/2021/01/06/icQvZnNy1zoHAdT.png) 12 | 13 | 加到应代码的url的subject后面数字位置即可 14 | 15 | ```python 16 | url_1 = "https://movie.douban.com/subject/27073752/comments?start=" 17 | ``` -------------------------------------------------------------------------------- /webcrawling/douban_score_analysis.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from collections import Counter 3 | 4 | #读取csv文件 5 | def score_analysis(output_file_name): 6 | df = pd.read_csv(output_file_name) 7 | 8 | #统计打分数量 9 | star_list = list(df['star'].values) 10 | num_count = Counter(star_list) 11 | #显示热评种不同分值的评论数量 12 | print("=================================分数统计==========================================") 13 | print(num_count) 14 | 15 | #分组求平均 16 | grouped = df.groupby('star').describe().reset_index() 17 | star = grouped['star'].values.tolist() 18 | print(star) 19 | 20 | #根据用户打分的分组,对每组的情感值求平均 21 | sentiment_average = df.groupby('star')['sentiment_score'].mean() 22 | sentiment_scores = sentiment_average.values 23 | print(sentiment_scores) 24 | print("===================================================================================") 25 | -------------------------------------------------------------------------------- /webcrawling/douban_wordcloud.py: -------------------------------------------------------------------------------- 1 | from wordcloud import WordCloud 2 | import jieba 3 | import numpy as np 4 | import PIL.Image as Image 5 | import pandas as pd 6 | 7 | 8 | def chinese_jieba(text): 9 | wordlist_jieba = jieba.cut(text) 10 | space_wordlist = " ".join([str(i) for i in wordlist_jieba]) 11 | return space_wordlist 12 | 13 | def WORDCLOAD(output_filename,wordcloud_name,stop_word,star): 14 | stop_words = pd.read_csv(stop_word, encoding='utf-8') 15 | # 读取csv文件 16 | df = pd.read_csv(output_filename) 17 | comment_list = df['comment'].values.tolist() 18 | star_list = list(df['star'].values) 19 | 20 | text = "" 21 | for jj in range(len(comment_list)): 22 | if star_list[jj] in star: 23 | text = text + chinese_jieba(comment_list[jj]) 24 | 25 | # 调用PIL中的open方法,读取图片文件,通过numpy中的array方法生成数组 26 | mask_pic = np.array(Image.open("background_love.jpg")) 27 | wordcloud = WordCloud(font_path="C:/Windows/Fonts/STZHONGS.TTF", 28 | mask=mask_pic, 29 | background_color='white', 30 | max_font_size=150, 31 | max_words=200, 32 | stopwords={i for i in set(stop_words.iloc[:,0])}, 33 | ).generate(text) 34 | image = wordcloud.to_image() 35 | #wordcloud.to_file('ciyun.png') 36 | wordcloud.to_file(wordcloud_name) 37 | image.show() -------------------------------------------------------------------------------- /webcrawling/main.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from douban_wordcloud import * 3 | from douban_sentiment_analysis import * 4 | from douban_score_analysis import * 5 | from douban_movie_comment import * 6 | def play(output_filename,header,Cookie,url_1,url_2,sleep_time,wordcloud_name,stop_word,star): 7 | crawl(output_filename,header,Cookie,url_1,url_2,sleep_time) 8 | sentiment_analysis(output_filename) 9 | score_analysis(output_filename) 10 | WORDCLOAD(output_filename,wordcloud_name,stop_word,star) 11 | 12 | if __name__=='__main__': 13 | #输出文件名 14 | output_filename = 'douban_movie_wonder_woman_1-5.csv' 15 | 16 | # url请求文件头,User-Agent要改为自己登录后的 17 | header = {'Content-Type': 'text/html; charset=utf-8', 18 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'} 19 | # 登录cookies,自己填写登录豆瓣后的cookie 20 | Cookie={ 21 | } 22 | # 构造请求网址 23 | url_1 = "https://movie.douban.com/subject/27073752/comments?start=" 24 | url_2 = "&limit=20&sort=new_score&status=P" 25 | #睡眠时间 26 | sleep_time =2 27 | #词云文件名 28 | wordcloud_name = 'ciyun.png' 29 | #停用词存放地址 30 | stop_word='hit_stopwords.txt' 31 | #生成词云要使用的评分,一共是1-5 32 | star=[5] 33 | 34 | #词云,对应8个参数为输出文件名,Cookie,url第一部分,url第二部分,睡眠时间,输出词云文件名,要看是哪些评星的词云 35 | play(output_filename,header,Cookie,url_1,url_2,sleep_time,wordcloud_name,stop_word,star) 36 | -------------------------------------------------------------------------------- /webcrawling/douban_sentiment_analysis.py: -------------------------------------------------------------------------------- 1 | # encoding=gbk 2 | import pandas as pd 3 | from snownlp import SnowNLP 4 | 5 | def sentiment_analysis(output_filename): 6 | df_1 = pd.read_csv(output_filename, header=None, usecols=[1, 2, 3, 4, 5]) 7 | df_1.columns = ['uname', 'comment', 'star', 'title', 'support'] 8 | # 填补空值 9 | df_1['comment'].fillna(" ",inplace=True) 10 | df_1['star'] = df_1['star'].astype(str) 11 | df_1['star'] = df_1['star'].str.replace("allstar", "") 12 | df_1['star'] = df_1['star'].str.replace("0", "") 13 | df_1['star'] = df_1['star'].apply(lambda x: 3 if len(x) > 1 or eval(x)> 5 else x) 14 | 15 | # df_1['star']=df_1['star'].str.replace("33","3") 16 | df_1['star'].fillna(3, inplace=True) 17 | # 读抓取的csv文件,标题在第三列,序号为2 18 | df = pd.read_csv(output_filename, header=None, usecols=[2]) 19 | 20 | # 将dataframe转换为List 21 | contents = df.values.tolist() 22 | # 数据长度 23 | 24 | # 定义空列表存储情感分值 25 | score = [] 26 | for content in contents: 27 | try: 28 | s = SnowNLP(content[0]) 29 | # print(s.summary()) 30 | score.append(s.sentiments) 31 | except: 32 | #TODO 检查错误要把这里加一个输出 33 | #print("") 34 | #自动填补为 35 | score.append(0.5) 36 | data2 = pd.DataFrame(score) 37 | # data2.to_csv('sentiment.csv',header=False,index=False,mode='a+') 38 | 39 | # 整理两个表格 40 | df_1['sentiment_score'] = data2 41 | 42 | df_1.to_csv(output_filename, index=False) 43 | -------------------------------------------------------------------------------- /webcrawling/douban_movie_comment.py: -------------------------------------------------------------------------------- 1 | # encoding = gbk 2 | 3 | import requests 4 | import pandas as pd 5 | import re 6 | import time 7 | import csv 8 | from bs4 import BeautifulSoup 9 | import os 10 | from urllib import request 11 | 12 | def crawl(output_filename,header,Cookie,url_1,url_2,sleep_time): 13 | i = 0 14 | while True: 15 | # 拼接url 16 | url = f"{url_1}{str(i * 20)}{url_2}" 17 | print(url) 18 | try: 19 | #request请求 20 | html = requests.get(url,headers=header,cookies=Cookie) 21 | #beautifulsoup 22 | soup = BeautifulSoup(html.content,'lxml') 23 | #评论时间 24 | comment_time_list = soup.find_all('span',attrs={'class':'comment-time'}) 25 | #设置循环终止变量 26 | if len(comment_time_list)==0: 27 | break 28 | #评论用户名 29 | use_name_list = soup.find_all('span',attrs={'class':'comment-info'}) 30 | #评论文本 31 | comment_list = soup.find_all('span',attrs={'class':'short'}) 32 | #评分 33 | rating_list = soup.find_all('span',attrs={'class':re.compile(r"allstar(\s\w+)?")}) 34 | #支持 35 | support_list = soup.find_all('span',attrs={'class':'votes vote-count'}) 36 | for jj in range(len(comment_time_list)): 37 | data1 = [(comment_time_list[jj].string, 38 | use_name_list[jj].a.string, 39 | comment_list[jj].string, 40 | rating_list[jj].get('class')[0], 41 | rating_list[jj].get('title'), 42 | support_list[jj].string)] 43 | data2 = pd.DataFrame(data1) 44 | data2.to_csv(output_filename,header=False,index=False,mode='a+') 45 | except Exception as E: 46 | print('something is wrong') 47 | print('page '+str(i+1)+' is done') 48 | i+=1 49 | time.sleep(sleep_time) 50 | -------------------------------------------------------------------------------- /webcrawling/hit_stopwords.txt: -------------------------------------------------------------------------------- 1 | 第二 2 | 一番 3 | 一直 4 | 一个 5 | 一些 6 | 许多 7 | 种 8 | 有的是 9 | 也就是说 10 | 末##末 11 | 啊 12 | 阿 13 | 哎 14 | 哎呀 15 | 哎哟 16 | 唉 17 | 俺 18 | 俺们 19 | 按 20 | 按照 21 | 吧 22 | 吧哒 23 | 把 24 | 电影 25 | 太 26 | 可能 27 | 没 28 | 分钟 29 | 里 30 | 中 31 | 作品 32 | 世界 33 | 已经 34 | 做 35 | 上 36 | 事情 37 | 部分 38 | 却是 39 | 拍 40 | 有点 41 | 罢了 42 | 被 43 | 本 44 | 本着 45 | 比 46 | 比方 47 | 比如 48 | 鄙人 49 | 彼 50 | 很 51 | 还 52 | 都 53 | 说 54 | 吗 55 | 看 56 | 真的 57 | 彼此 58 | 边 59 | 别 60 | 别的 61 | 别说 62 | 并 63 | 并且 64 | 不 65 | 大 66 | 小 67 | 中 68 | 不比 69 | 不成 70 | 不单 71 | 不但 72 | 不独 73 | 不管 74 | 不光 75 | 不过 76 | 不仅 77 | 不拘 78 | 不论 79 | 不怕 80 | 不然 81 | 不如 82 | 不特 83 | 不惟 84 | 不问 85 | 不只 86 | 朝 87 | 朝着 88 | 趁 89 | 趁着 90 | 乘 91 | 冲 92 | 除 93 | 除此之外 94 | 除非 95 | 这部 96 | 没有 97 | 其实 98 | 后 99 | 表达 100 | 却 101 | 年 102 | 点 103 | 难得 104 | 两个 105 | 三个 106 | 四个 107 | 五个 108 | 六个 109 | 七个 110 | 八个 111 | 九个 112 | 十个 113 | 片 114 | 看到 115 | 觉得 116 | 感觉 117 | 类型 118 | 情节 119 | 更是 120 | 推向 121 | 整体 122 | 之间 123 | 这部 124 | 除了 125 | 此 126 | 一起 127 | 非常 128 | 每个 129 | 此间 130 | 此外 131 | 从 132 | 从而 133 | 打 134 | 待 135 | 但 136 | 但是 137 | 当 138 | 当着 139 | 到 140 | 得 141 | 的 142 | 的话 143 | 等 144 | 等等 145 | 地 146 | 第 147 | 叮咚 148 | 对 149 | 对于 150 | 多 151 | 多少 152 | 而 153 | 而况 154 | 而且 155 | 而是 156 | 而外 157 | 而言 158 | 而已 159 | 尔后 160 | 反过来 161 | 反过来说 162 | 反之 163 | 非但 164 | 非徒 165 | 否则 166 | 嘎 167 | 嘎登 168 | 该 169 | 赶 170 | 个 171 | 各 172 | 各个 173 | 各位 174 | 各种 175 | 各自 176 | 给 177 | 根据 178 | 跟 179 | 故 180 | 故此 181 | 固然 182 | 关于 183 | 管 184 | 归 185 | 果然 186 | 果真 187 | 过 188 | 哈 189 | 哈哈 190 | 呵 191 | 和 192 | 何 193 | 何处 194 | 何况 195 | 何时 196 | 嘿 197 | 哼 198 | 哼唷 199 | 呼哧 200 | 乎 201 | 哗 202 | 还是 203 | 还有 204 | 换句话说 205 | 换言之 206 | 或 207 | 或是 208 | 或者 209 | 极了 210 | 及 211 | 及其 212 | 及至 213 | 即 214 | 即便 215 | 即或 216 | 即令 217 | 即若 218 | 即使 219 | 几 220 | 几时 221 | 己 222 | 既 223 | 既然 224 | 既是 225 | 继而 226 | 加之 227 | 假如 228 | 假若 229 | 假使 230 | 鉴于 231 | 将 232 | 较 233 | 较之 234 | 叫 235 | 接着 236 | 结果 237 | 借 238 | 紧接着 239 | 进而 240 | 尽 241 | 尽管 242 | 经 243 | 经过 244 | 就 245 | 就是 246 | 就是说 247 | 据 248 | 具体地说 249 | 具体说来 250 | 开始 251 | 开外 252 | 靠 253 | 咳 254 | 可 255 | 可见 256 | 可是 257 | 可以 258 | 况且 259 | 啦 260 | 来 261 | 来着 262 | 离 263 | 例如 264 | 哩 265 | 连 266 | 连同 267 | 两者 268 | 了 269 | 临 270 | 另 271 | 另外 272 | 另一方面 273 | 论 274 | 嘛 275 | 吗 276 | 慢说 277 | 漫说 278 | 冒 279 | 么 280 | 每 281 | 每当 282 | 们 283 | 莫若 284 | 某 285 | 某个 286 | 某些 287 | 拿 288 | 哪 289 | 哪边 290 | 哪儿 291 | 哪个 292 | 哪里 293 | 哪年 294 | 哪怕 295 | 哪天 296 | 哪些 297 | 哪样 298 | 那 299 | 那边 300 | 那儿 301 | 那个 302 | 那会儿 303 | 那里 304 | 那么 305 | 那么些 306 | 那么样 307 | 那时 308 | 那些 309 | 那样 310 | 乃 311 | 乃至 312 | 呢 313 | 能 314 | 你 315 | 你们 316 | 您 317 | 宁 318 | 宁可 319 | 宁肯 320 | 宁愿 321 | 哦 322 | 呕 323 | 啪达 324 | 旁人 325 | 呸 326 | 凭 327 | 凭借 328 | 其 329 | 其次 330 | 其二 331 | 其他 332 | 其它 333 | 其一 334 | 其余 335 | 其中 336 | 起 337 | 起见 338 | 起见 339 | 岂但 340 | 恰恰相反 341 | 前后 342 | 前者 343 | 且 344 | 然而 345 | 然后 346 | 然则 347 | 让 348 | 人家 349 | 任 350 | 任何 351 | 任凭 352 | 如 353 | 如此 354 | 如果 355 | 如何 356 | 如其 357 | 如若 358 | 如上所述 359 | 若 360 | 若非 361 | 若是 362 | 啥 363 | 上下 364 | 尚且 365 | 设若 366 | 设使 367 | 甚而 368 | 甚么 369 | 甚至 370 | 省得 371 | 时候 372 | 什么 373 | 什么样 374 | 使得 375 | 是 376 | 是的 377 | 首先 378 | 谁 379 | 谁知 380 | 顺 381 | 顺着 382 | 似的 383 | 虽 384 | 虽然 385 | 虽说 386 | 虽则 387 | 随 388 | 随着 389 | 所 390 | 所以 391 | 他 392 | 他们 393 | 他人 394 | 它 395 | 它们 396 | 她 397 | 她们 398 | 倘 399 | 倘或 400 | 倘然 401 | 倘若 402 | 倘使 403 | 腾 404 | 替 405 | 通过 406 | 同 407 | 同时 408 | 哇 409 | 万一 410 | 往 411 | 望 412 | 为 413 | 为何 414 | 为了 415 | 为什么 416 | 为着 417 | 喂 418 | 嗡嗡 419 | 我 420 | 我们 421 | 呜 422 | 呜呼 423 | 乌乎 424 | 无论 425 | 无宁 426 | 毋宁 427 | 嘻 428 | 吓 429 | 相对而言 430 | 像 431 | 向 432 | 向着 433 | 嘘 434 | 呀 435 | 焉 436 | 沿 437 | 沿着 438 | 要 439 | 要不 440 | 要不然 441 | 要不是 442 | 要么 443 | 那种 444 | 真 445 | 下 446 | 一部 447 | 不是 448 | 要是 449 | 也 450 | 也罢 451 | 也好 452 | 一 453 | 一般 454 | 一旦 455 | 一方面 456 | 一来 457 | 一切 458 | 一样 459 | 一则 460 | 依 461 | 依照 462 | 矣 463 | 以 464 | 以便 465 | 以及 466 | 以免 467 | 以至 468 | 以至于 469 | 以致 470 | 抑或 471 | 因 472 | 因此 473 | 因而 474 | 因为 475 | 哟 476 | 用 477 | 由 478 | 由此可见 479 | 由于 480 | 有 481 | 有的 482 | 有关 483 | 有些 484 | 又 485 | 于 486 | 于是 487 | 于是乎 488 | 与 489 | 与此同时 490 | 与否 491 | 与其 492 | 越是 493 | 云云 494 | 哉 495 | 再说 496 | 再者 497 | 在 498 | 在下 499 | 咱 500 | 咱们 501 | 则 502 | 怎 503 | 怎么 504 | 怎么办 505 | 怎么样 506 | 怎样 507 | 咋 508 | 照 509 | 照着 510 | 者 511 | 这 512 | 这边 513 | 这儿 514 | 这个 515 | 这会儿 516 | 这就是说 517 | 这里 518 | 这么 519 | 这么点儿 520 | 这么些 521 | 这么样 522 | 这时 523 | 这些 524 | 这样 525 | 正如 526 | 吱 527 | 之 528 | 之类 529 | 之所以 530 | 之一 531 | 只是 532 | 只限 533 | 只要 534 | 只有 535 | 至 536 | 至于 537 | 诸位 538 | 着 539 | 着呢 540 | 自 541 | 自从 542 | 自个儿 543 | 自各儿 544 | 自己 545 | 自家 546 | 自身 547 | 综上所述 548 | 总的来看 549 | 总的来说 550 | 总的说来 551 | 总而言之 552 | 总之 553 | 纵 554 | 纵令 555 | 纵然 556 | 纵使 557 | 遵照 558 | 作为 559 | 兮 560 | 呃 561 | 呗 562 | 咚 563 | 咦 564 | 喏 565 | 啐 566 | 喔唷 567 | 嗬 568 | 嗯 569 | 嗳 570 | --------------------------------------------------------------------------------