资讯专栏INFORMATION COLUMN

python数据分析微博热门

firim / 1328人阅读

摘要:前者对中文进行分词后者图形化展示词语的出现频率。众所周知,中文系的语言处理恐怕是最难的自然语言处理的语种。研究中文自然语言处理将是一个长久而大的工程,对于分析数据我们不是要研究自然语言处理

</>复制代码

  1. 接上篇,这一篇将从技术层面讲讲是如何实现的。阅读本文您将会了解如何用python爬取微博的评论以及如何用python word_cloud库进行数据可视化。

上一篇:程序员代码下的许豪杰

准备工作

打开微博pc m站并找到许豪杰该条微博地址:https://m.weibo.cn/status/413...

为什么要用m站地址?因为m站可以直接抓取到api json数据,而pc站虽然也有api返回的是html,相比而言选取m站会省去很多麻烦

打开该页面,并且用chrome 的检查工具 查看network,可以获取到评论的api地址。

数据抓取

首先观察api返回

从返回地址上可以看到可以通过参数page 改变请求的页码,并且每页都回返回总条数和总页码数。这里我决定采用多线程来抓去(其实数据量不大,也可以单线程跑)。

其中在爬取数据的时候会面临几个问题:

1.存储选择

我这里选用了MongoDB作为数据存储,因为api通常返回的是json数据而json结构和MongoDB的存储方式可以结合的很默契,不需要经过任何处理可以直接的进行插入。

2.防爬虫

很多网站可能会做一些防爬虫的处理,面对同一个请求ip的短时间的高频率请求会进行服务隔断(直接告诉你服务不可用),这个时候可以去网上找一些代理进行请求。

3.多线程的任务分配

采用多线程爬取你当然不能让多个线程去爬取同样的链接做别人已经做过的事情,那样多线程毫无意义。所以你需要制定一套规则,让不同线程爬取不同的链接。

</>复制代码

  1. # coding=utf-8
  2. from __future__ import division
  3. from pymongo import MongoClient
  4. import requests
  5. import sys
  6. import re
  7. import random
  8. import time
  9. import logging
  10. import threading
  11. import json
  12. from os import path
  13. import math
  14. # 爬取微博评论
  15. # m站微博地址
  16. weibo_url = "https://m.weibo.cn/status/4132385564040383"
  17. thread_nums = 5 #线程数
  18. #代理地址
  19. proxies = {
  20. "http": "http://171.92.4.67:9000",
  21. "http": "http://163.125.222.240:8118",
  22. "http": "http://121.232.145.251:9000",
  23. "http": "http://121.232.147.247:9000",
  24. }
  25. # 创建 日志 对象
  26. logger = logging.getLogger()
  27. handler = logging.StreamHandler()
  28. formatter = logging.Formatter(
  29. "%(asctime)s %(name)-12s %(levelname)-8s %(message)s")
  30. handler.setFormatter(formatter)
  31. logger.addHandler(handler)
  32. logger.setLevel(logging.DEBUG)
  33. mongoconn = MongoClient("127.0.0.1", 27017)
  34. mdb = mongoconn.data_analysis
  35. das_collection = mdb.weibo
  36. weiboid_reobj = re.match(r".*status/(d+)", weibo_url)
  37. weibo_id = weiboid_reobj.group(1)
  38. def scrapy_comments(weibo_id, page):
  39. weibo_comment_url = "https://m.weibo.cn/api/comments/show?id=%s&page=%d" % (
  40. weibo_id, page)
  41. res = requests.get(weibo_comment_url)
  42. res_obj = json.loads(res.content)
  43. return res_obj
  44. def import_comments(threadName, weibo_id, page_start, page_end):
  45. logger.info("开始线程:%s" % threadName)
  46. for page in range(page_start, page_end + 1):
  47. logging.info("读取第%s页" % page)
  48. time.sleep(1)
  49. # continue
  50. try:
  51. res_obj = scrapy_comments(weibo_id, page)
  52. logging.info("该页有%s条记录" % len(res_obj["data"]))
  53. except:
  54. logging.error("读取%s页时发生错误" % page)
  55. continue
  56. if res_obj["ok"] == 1:
  57. comments = res_obj["data"]
  58. for comment in comments:
  59. comment_text = re.sub(
  60. r"]*>", "", comment["text"]).encode("utf-8")
  61. if re.search(r"回复@.*:", comment_text):
  62. # 过滤掉回复别人的评论
  63. continue
  64. comment["text"] = comment_text
  65. comment["weibo_id"] = weibo_id
  66. logging.info("读取评论:%s" % comment["id"])
  67. try:
  68. if das_collection.find_one({"id": comment["id"]}):
  69. logging.info("在mongodb中存在")
  70. else:
  71. logging.info("插入记录:%s" % comment["id"])
  72. das_collection.insert_one(comment)
  73. except:
  74. logging.error("mongodb发生错误")
  75. else:
  76. logging.error("读取第%s页时发生错误" % page)
  77. logging.info("线程%s结束" % threadName)
  78. # res_obj = scrapy_comments(weibo_id, page)
  79. if __name__ == "__main__":
  80. # 分配不同链接到不同的线程上去
  81. res_obj = scrapy_comments(weibo_id, 1)
  82. if res_obj["ok"] == 1:
  83. total_number = res_obj["total_number"]
  84. logging.info("该条微博有:%s条评论" % total_number)
  85. max_page = res_obj["max"]
  86. page_nums = math.ceil(max_page / thread_nums)
  87. else:
  88. raise
  89. # print max_page
  90. # print page_nums
  91. for i in range(1, thread_nums + 1):
  92. if i < thread_nums:
  93. page_end = page_nums * i
  94. else:
  95. page_end = max_page
  96. page_start = (i - 1) * page_nums + 1
  97. t = threading.Thread(target=import_comments, args=(
  98. i, weibo_id, int(page_start), int(page_end)))
  99. t.start()
数据整理可视化(data visualization)

运行脚本完毕,我的MongoDB得到了2万多条评论数据,接下来要做的事是对这部分数据进行提取、清洗、结构化等操作。这里顺便说明一下python 数据分析的 大致基本流程。

1.与外界进行交互
这个过程包括数据的获取、读取。不管是从网络资源上爬取、还是从现有资源(各样的文件如文本、excel、数据库存储对象)

2.准备工作
对数据进行清洗(cleaning)、修整(munging)、整合(combining)、规范化(normalizing)、重塑(reshaping)、切片(slicing)和切块(dicing)

3.转换
对数据集做一些数学和统计运算产生新的数据集

4.建模和计算
将数据跟统计模型、机器学习算法或其他计算工具联系起来

5.展示
创建交互式的或静态的图片或文字摘要

下面我们来进行2、3及5的工作:

</>复制代码

  1. # coding=utf-8
  2. import sys
  3. from pymongo import MongoClient
  4. import random
  5. # 分词库
  6. # from snownlp import SnowNLP
  7. import jieba
  8. import uniout
  9. from collections import Counter, OrderedDict
  10. # 词语云 文本统计可视化库
  11. from wordcloud import WordCloud
  12. mongoconn = MongoClient("127.0.0.1", 27017)
  13. mdb = mongoconn.data_analysis
  14. das_collection = mdb.weibo
  15. total_counts = das_collection.find().count()
  16. # random_int = random.randint(0, total_counts - 1)
  17. docs = das_collection.find()
  18. print docs.count()
  19. words_counts = {}
  20. for doc in docs:
  21. print doc
  22. comment_text = doc["text"].encode("utf-8")
  23. if len(comment_text) == 0:
  24. continue
  25. words = jieba.cut(comment_text)
  26. for word in words:
  27. if word not in words_counts:
  28. words_counts[word] = 1
  29. else:
  30. words_counts[word] += 1
  31. for word in words_counts.keys():
  32. if words_counts[word] < 2 or len(word) < 2:
  33. del words_counts[word]
  34. # print words_counts.items()
  35. #注意要让中文不乱码要指定中文字体
  36. #fit_words 接收参数是dict eg:{"你":333,"好":23} 文字:出现次数
  37. wordcloud = WordCloud(
  38. font_path="/Users/cwp/font/msyh.ttf",
  39. background_color="white",
  40. width=1200,
  41. height=1000
  42. ).fit_words(words_counts)
  43. import matplotlib.pyplot as plt
  44. plt.imshow(wordcloud, interpolation="bilinear")
  45. plt.axis("off")
  46. plt.show()

介绍下以上代码:
我们主要用到了2个工具,jieba和word_cloud。前者对中文进行分词后者图形化展示词语的出现频率。
众所周知,中文系的语言处理恐怕是最难的自然语言处理(NLP)的语种。就基本的分词而言都是一项比较困难的工作,(英语句子中每个单词都是有空格分开的,而中文是由单个字组成词连接成串组成句).
举个例子,请用“孩提”造句,"那个男孩提交完代码就下班了"。如果人工分词,可以知道"男孩"和"提交"应该是分开的2个词,但是对于机器而言,要辨别"提"应该与"男"还是"交"进行组词就很难办了。要想机器能够更精确的辨别这类问题,就需要让机器不停学习,让它知道这种情况该这么分而不是那么分。研究中文自然语言处理将是一个长久而大的工程,对于分析数据(我们不是要研究自然语言处理

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/43415.html

相关文章

  • 一款产品的从0到1之旅

    摘要:从到打造一款产品是一种什么样的体验为了回答这种知乎范的问题,让我来介绍下我是如何打造交易日记这款的过程。社会对群体聚集进行生产产品的模式需求在降低。这在接下来的部分我会介绍我如何在三个月内完成一款产品从到的过程。 从0到1打造一款产品是一种什么样的体验?为了回答这种知乎范的问题,让我来介绍下我是如何打造交易日记这款App的过程。需要提前说明的是整款iOS APP的全部工作都是我一个人完...

    _ivan 评论0 收藏0
  • 一款产品的从0到1之旅

    摘要:从到打造一款产品是一种什么样的体验为了回答这种知乎范的问题,让我来介绍下我是如何打造交易日记这款的过程。社会对群体聚集进行生产产品的模式需求在降低。这在接下来的部分我会介绍我如何在三个月内完成一款产品从到的过程。 从0到1打造一款产品是一种什么样的体验?为了回答这种知乎范的问题,让我来介绍下我是如何打造交易日记这款App的过程。需要提前说明的是整款iOS APP的全部工作都是我一个人完...

    wangdai 评论0 收藏0
  • PHP 基于laravel框架获取微博数据之二 用户数据的使用

    摘要:以大量微博用户数据为基础可建立数据模型。当前微博除了用户自己,其他人是不能查看该用户所有粉丝数据的。 项目地址:https://github.com/daweilang/... 开始抓取微博数据的时候,只是想获得一条热门微博下的所有评论,因为里面有不少图片广告,所以想试试能不能分析出热门微博评论里的异常用户。 使用PHP的Laravel框架后,通过队列、命令等各种功能,最后构架了一套完...

    Sleepy 评论0 收藏0

发表评论

0条评论

firim

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<