CSDN 2021-2022年微博情感数据分析

Posted Mr数据杨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSDN 2021-2022年微博情感数据分析相关的知识,希望对你有一定的参考价值。

新年第一篇,承蒙邹总邀请 一个实际的大数据分析例子

CSDN 上已经有很多关于 虫* 的博客和代码,还有很多关于 情感分析 的研究和实战例子,既然大家对这个技术都这么感兴趣,我们就来一个真实的例子,看看大家在解决实际问题的能力如何。 CSDN 的很多用户都在各个微信群、社区里面表达过对 CSDN 的各种反馈,这些人和众多普通用户相比,还是很少的一部分,那么,我们怎样收集到散落在网上的各种反馈和评论,并做定性、定量的分析呢? 这就需要数据挖掘、自然语言处理、情感分析、和数据可视化的技巧了。

快来看看过去的2年中你心中的CSDN情感评价是否是这样的?

微博情感分析是一种用于提取微博文本中的情感倾向的方法。它可以帮助企业了解人们对于某个主题的看法和态度。

如果要进行微博情感分析,需要准备一些微博数据。可以使用爬虫程序爬取相关微博数据,这里使用的 Scrapy 框架进行的数据爬虫。可以使用文本分类模型对微博数据进行情感分类。在这里准备了一些情感标签(例如“正面”、“负面”、“中立”),并为每条微博打上标签。

此外,可以使用自然语言处理技术来提取微博中的关键词和主题,以便更好地了解人们关注的焦点。总的来说微博情感分析是一种有用的工具,可以帮助您更好地了解人们对于某个主题的看法和态度。

接下来让我们看看如何实现的吧,以及这两年CSDN的外部综合评价是否和你想的一样。

文章目录

Scrapy 网络爬虫

这里使用的 Scrapy 框架是 2.6.x 框架,由于整个过程中没有被微博服务器反爬,因此就没有浪费代理池的资源,不过在框架代码中我按照习惯还是设置了。

Scrapy 核心代码

settings.py,这里主要配置了爬虫的客户端以及抓取微博数据需要设置的 Cookie 信息,在每次启动爬虫任务的时候需要自己手动更新 Cookie 进行替换。

打码的地方自己完全复制过来就好了。

BOT_NAME = 'spider'

SPIDER_MODULES = ['spiders']
NEWSPIDER_MODULE = 'spiders'

ROBOTSTXT_OBEY = False

with open('cookie.txt', 'rt', encoding='utf-8') as f:
    cookie = f.read().strip()
DEFAULT_REQUEST_HEADERS = 
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0',
    'Cookie': cookie


CONCURRENT_REQUESTS = 16

DOWNLOAD_DELAY = 1

DOWNLOADER_MIDDLEWARES = 
    'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': None,
    'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': None,
    'middlewares.IPProxyMiddleware': 100,
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 101,


ITEM_PIPELINES = 
    'pipelines.JsonWriterPipeline': 300,


pipelines.py,这里设置的将数据写入项目目录下 output 文件夹并将每一条抓取的数据依次写入 json 文件中。

    def __init__(self):
        self.file = None
        if not os.path.exists('../output'):
            os.mkdir('../output')

    def process_item(self, item, spider):
        """
        处理item
        """
        if not self.file:
            now = datetime.datetime.now()
            file_name = spider.name + "_" + now.strftime("%Y%m%d%H%M%S") + '.json'
            self.file = open(f'../output/file_name', 'wt', encoding='utf-8')
        item['crawl_time'] = int(time.time())
        line = json.dumps(dict(item), ensure_ascii=False) + "\\n"
        self.file.write(line)
        self.file.flush()
        return item

middlewares.py,中间件这里我用的自己的代理一直没更换过 IP ,之前也说了没有被反爬,所以用不用的无所谓了。

    def process_request(self, request, spider):
        """
        将代理IP添加到request请求中
        """
        proxy_data = self.fetch_proxy()
        if proxy_data:
            current_proxy = f'http://127.0.0.1:19180'
            spider.logger.debug(f"current proxy:current_proxy")
            request.meta['proxy'] = current_proxy

search.spider.py ,核心的抓取数据代码。这里搜索的关键词是 『CSDN』,然后以日为单位遍历从2021年1月1号,到2022年12月28日的数据进行抓取,如果有多页就自动翻页进行获取,将结果保存到 json 文件中。

class SearchSpider(Spider):
    """
    关键词搜索采集
    """
    name = "search_spider"
    base_url = "https://s.weibo.com/"

    def start_requests(self):
        """
        爬虫入口
        """
        keywords = ['CSDN']
        time_list = [
            ["2021-01-01-0", "2021-01-01-23"],
            ["2021-01-02-0", "2021-01-02-23"],
            .......
            ["2022-12-27-0", "2022-12-27-23"],
            ["2022-12-28-0", "2022-12-28-23"],
        ]
        is_search_with_specific_time_scope = True 
        is_sort_by_hot = False 
        for i in time_list:
            for keyword in keywords:
                if is_search_with_specific_time_scope:
                    url = f"https://s.weibo.com/weibo?q=keyword&timescope=custom%3Ai[0]%3Ai[1]&page=1"
                else:
                    url = f"https://s.weibo.com/weibo?q=keyword&page=1"
                if is_sort_by_hot:
                    url += "&xsort=hot"
                yield Request(url, callback=self.parse, meta='keyword': keyword)

    def parse(self, response, **kwargs):
        """
        网页解析
        """
        html = response.text
        tweet_ids = re.findall(r'\\d+/(.*?)\\?refer_flag=1001030103_" ', html)
        for tweet_id in tweet_ids:
            url = f"https://weibo.com/ajax/statuses/show?id=tweet_id"
            yield Request(url, callback=self.parse_tweet, meta=response.meta)
        next_page = re.search('<a href="(.*?)" class="next">下一页</a>', html)

        if next_page:
            url = "https://s.weibo.com" + next_page.group(1)
            yield Request(url, callback=self.parse, meta=response.meta)

    @staticmethod
    def parse_tweet(response):
        """
        解析推文
        """
        data = json.loads(response.text)
        item = parse_tweet_info(data)
        item['keyword'] = response.meta['keyword']
        if item['isLongText']:
            url = "https://weibo.com/ajax/statuses/longtext?id=" + item['mblogid']
            yield Request(url, callback=parse_long_tweet, meta='item': item)
        else:
            yield item

Scrapy 启动

启动脚本开始挂机,整个过程大概持续了不到 2个钟头。

抓取数据后这里将2021年和2022年的数据分开进行保存。

这里的数据基本都是页面上能看到的数据信息,但是不包括点击加载的每条微博的评论数据,只有最基础的发帖数据信息。

Python 数据分析

首先加载必要的三方库,功能不知道干嘛用的自行百度或者看下面的代码。

import pandas as pd
import json
import time
import re
from pandas.io.json import json_normalize

from wordcloud import WordCloud
import matplotlib.pyplot as plt 
 
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

from pyecharts import options as opts
from pyecharts.charts import Pie, Timeline

构建情感分类信息

这里使用的百度API的接口,然后根据置信度和倾向程度又进行了细分操作,将原有的『正面』、『负面』、『中性』进行细分成『非常正面』、『正面』、『非常负面』、『负面』、『中性』这5类。

不过在分类之前我们要获取能进行该操作的基础数据。

读取 json 数据构建 DataFrame。

with open("search_CSDN_2021.json",encoding='utf8') as f:
    data = f.readlines()
    
data = [json.loads(i.replace("\\n","")) for i in data]

df = pd.DataFrame(data)
df.head(2)


使用『百度API』情感分类功能进行建模应用,具体接口操作不会的自行百度API文档。

def getToken():
    host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + API_Key + '&client_secret=' + Secret_Key
    response = requests.get(host)

    if response.status_code == 200: 
        info = json.loads(response.text) 
        access_token = info['access_token'] 
        return access_token
    return ''

accessToken = getToken()

def getEmotion(inputText):
    time.sleep(1)
    url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/sentiment_classify?access_token=' + accessToken
    header = 'Content-Type ': 'application/json'
    body = 'text': inputText
    requests.packages.urllib3.disable_warnings()
    res = requests.post(url=url, data=json.dumps(body), headers=header, verify=False)
    if res.status_code == 200:
        info = json.loads(res.text)
    return str(info)

使用 apply 函数构建的方式将结果保存到 sentiment 字段并进行保存 excel 表单。

df["sentiment"] = df.content.apply(getEmotion)
df.to_excel("data.xlsx")

其中获取到情感分类的数据信息大致是这样的。

'text': '望着CSDN的会员价格,在思考这和花1K买个毕设的区别在哪', 'items': ['confidence': 0.0389296, 'negative_prob': 0.567518, 'positive_prob': 0.432482, 'sentiment': 0], 'log_id': 1608337687190572820

这里所有数据都保存到表单进行后期的加工。

基础数据清洗整理

将正面概率、负面概率、置信度、类别提取到新的字段中。

def confidence_(text):
    try:
        test=re.sub('\\'','\\"',text)
        data = json.loads(test)
        return data["items"][0]["confidence"]
    except:
        return "-"

def negative_prob_(text):
    try:
        test=re.sub('\\'','\\"',text)
        data = json.loads(test)
        return data["items"][0]["negative_prob"]
    except:
        return "-"
    
def positive_prob_(text):
    try:
        test=re.sub('\\'','\\"',text)
        data = json.loads(test)
        return data["items"][0]["positive_prob"]
    except:
        return "-"
    
def sentiment_(text):
    try:
        test=re.sub('\\'','\\"',text)
        data = json.loads(test)
        return data["items"][0]["sentiment"]
    except:
        return "-"


df["confidence_"] = df.sentiment.apply(confidence_)
df["negative_prob_"] = df.sentiment.apply(negative_prob_)
df["positive_prob_"] = df.sentiment.apply(positive_prob_)
df["sentiment_"] = df.sentiment.apply(sentiment_)

拆解日期数据,只要每天的数据信息字段,例如『2022-01-01』这样。

def split_date(text):
    return text.split(" ")[0]

df["created_at_date"] = df.created_at.apply(split_date)

词云可视化

这里对全部的发帖信息汇总到一起按照2021年和2022年这样对比来看。

这里根据不同的情感『正面』、『负面』、『中性』以及全部的内容进行词云可视化方便小伙伴对比。

友情提示:图片上图为2021年、下图为2022年。

全部词云可视化

text = " ".join(review for review in df["content"])
wordcloud = WordCloud(font_path="simsun.ttc").generate(text)
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()



正面词云可视化

data = df[df["sentiment_"]==2]["content"]
data.reset_index(drop=True,inplace=True)

text = " ".join(review for review in data)
wordcloud = WordCloud(font_path="simsun.ttc").generate(text)
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()


负面词云可视化

data = df[df["sentiment_"]==0]["content"]
data.reset_index(drop=True,inplace=True)

text = " ".join(review for review in data)
wordcloud = WordCloud(font_path="simsun.ttc").generate(text)
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()

中性词云可视化

data = df[df["sentiment_"]==1]["content"]
data.reset_index(drop=True,inplace=True)

text = " ".join(review for review in data)
wordcloud = WordCloud(font_path="simsun.ttc").generate(text)
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()


年度用户发帖量对比

这里除了CSDN官方和邹老板以外一个都不认识 - -~。

def nick_name(text):
    text = re.sub('\\'','\\"',text)
    text = re.sub('False','"-"',text)
    text = re.sub('True','"-"',text)
    data = json.loads(text)
    return data["nick_name"]

df["nick_name"] = df.user.apply(nick_name)

nick_name_counts = df.groupby('nick_name')['nick_name'].count()
sorted_nick_name_counts = nick_name_counts.sort_values(ascending=False)
sorted_nick_name_counts.head(20)

用户发帖渠道对比

先说结论,在微博上看 CSDN 的都是有钱人。

source_counts = df.groupby('source')['source'].count()
sorted_source_counts = source_counts.sort_values(ascending=False)
sorted_source_counts.head(20)

用户发帖时间

这里按照每小时切分进行对比,符合程序员日常活动时间范围。

df = pd.read_excel("data.xlsx")
def hour_(text):
    return text.split(" ")[1].split(":")[0]

df["hour_"] = df.created_at.apply(hour_)

hour_counts = df.groupby(['hour_'])['hour_'].count()
hour_counts.plot.bar()
plt.show()


每月用户情感倾向

这里把情感细分成『非常正面』、『正面』、『非常负面』、『负面』、『中性』5中,

def month_(text):
    return text.split("-")[1]

df["month_"] = df.created_at_date.apply(month_)

data = df[df["sentiment_"] != "-"]

def sentiment_type(text):
    test=re.sub('\\'','\\"',text)
    data = json.loads(test)
    type_data_num = data["items"][0]
#     print(type_data_num)
    
    if type_data_num['sentiment'] ==

csdn的服务

IT人才服务:CSDNIT人才服务是CSDN结合自身专业优势,为企业和个人提供的一项特色服务。服务基于CSDN人才频道,利用专业化和个性化的服务手段,在IT人才和IT厂商之间搭起一个有 效的人才输送服务的桥梁。 

CSDN人才频道是融合企业服务和个人服务为一体的IT专业人才信息与服务平台,为IT专业人士提供关于企业招聘信息、人才动向、职业发展、职场热点、培训学习等相关知识和信息,为IT企业提供关于企业招聘信息发布、企业文化推广、人才推荐、简历筛选、人才测评、高级技术人才猎头等专业IT人才服务。

以上内容参考 百度百科-csdn

参考技术A 是说 www.csdn.net 这个编程网站,他是国内一个很大,很好的编程网站
中文是 中国软件开发网 如果你学编程什么滴不妨上去浏览一下不错滴
参考技术B chinese software develop net
中国软件开发联盟本回答被提问者采纳

以上是关于CSDN 2021-2022年微博情感数据分析的主要内容,如果未能解决你的问题,请参考以下文章

markdown 2019年微博

大数据分析案例-基于逻辑回归算法构建微博评论情感分类模型

Bilstm中文微博多情感分析

微博情感分析

NLPCC2013中文微博细粒度情感识别

Python 基于机器学习的微博情感分析与研究