专栏首页源懒由码python 舆情分析 nlp主题分析 (1) 待续

python 舆情分析 nlp主题分析 (1) 待续

参考资料: https://blog.csdn.net/Eastmount/article/details/50891162 # 该博主有很多篇幅,解释算法原理,算法应用。

需求:一直想试试大数据+舆情分析,虽然数据量不是很大,大概应用一下,看看是否能从海量数据中,提取出主题思想,以看看当前的舆论导向。

具体应用案例:

微博热门话题:#中印双方达成五点共识# 阅读量2.4亿,讨论7430条。

1、数据采集,使用python+selenium,采集该话题下的博文及作者信息,以及每个博文下的评论及作者信息;

2、数据预处理,采用Jieba库,构建用户词典,以达到更好的分词;情感分析,采用snownlp库,寻找政治类积极和负面词向量做一个训练,再进行评论分类;

3、对博文及评论作者信息进行分析,查看调查主体的用户类别概况;

4、lda主题分析,对博文做主题分析,依据top3主题关键字,对博文群主类看法进行分析;对正、负向评论做一次主题分析,并分别分析观点;

本编主要先完成第一步,后续再继续更新。

1、打开浏览器,手工登录微博,这里因为微博登录太严格(需要短信验证才能登录),所以直接人工登录。

%%time
# 配置浏览器
options = webdriver.ChromeOptions()
# 此步骤很重要,设置为开发者模式,防止被各大网站识别出来使用了Selenium
options.add_experimental_option('excludeSwitches', ['enable-automation']) 
# 进入网页
browser = webdriver.Chrome(options=options)
wait = WebDriverWait(browser,2)
browser.get('https://s.weibo.com/weibo?q=%23%E4%B8%AD%E5%8D%B0%E5%8F%8C%E6%96%B9%E8%BE%BE%E6%88%90%E4%BA%94%E7%82%B9%E5%85%B1%E8%AF%86%23')

2.1、分析微博页面,在博文页可以发现,是分页展示,下一页需要通过点击下一页进入。博文内容在'//div[@class="card"]'中。此处需要获取作者名称、作者主页链接、博文内容、博文url(为下一步获取评论准备)、发表日期、收藏、转发、评论、点赞数目。

%%time
list_ct = []    # 存储文章内容

while True:
    # 扫描文章内容,扫描一页,判断是否还有下一页
    wait.until(EC.presence_of_element_located((By.XPATH,'//div[@class="card"]/div[@class="card-feed"]/div[@class="content"]')))
    # 获取博文列表
    list_el = browser.find_elements_by_xpath('//div[@class="card"]')
    try:
        for l in list_el:
            actor_url = actor_name = content = content_url =content_date = sg = zf = pl = dz = ''
            try:
                # 获取作者
                t = l.find_element_by_xpath('./div[@class="card-feed"]/div[@class="content"]/div[@class="info"]/div[2]/a')
                actor_url = t.get_attribute('href')
                actor_name = t.text
                
                # 博文内容
                t = l.find_elements_by_xpath('./div[@class="card-feed"]/div[@class="content"]/p[@class="txt"]')
                if len(t) > 1:
                    content = t[1].get_attribute('innerText')
                else:
                    content = t[0].get_attribute('innerText')
                    
                # 博文链接
                t = l.find_element_by_xpath('./div[@class="card-feed"]/div[@class="content"]/p[@class="from"]/a')
                content_url = t.get_attribute('href')
                content_date = t.text
                
                # 收藏、转发、评论、点赞
                t = l.find_elements_by_xpath('./div[@class="card-act"]/ul/li')
                sg = t[0].get_attribute('innerText')
                zf = t[1].get_attribute('innerText')
                pl = t[2].get_attribute('innerText')
                dz = t[3].get_attribute('innerText')
            except Exception as e:
                pass
            # 追加
            list_ct.append([actor_url , actor_name , content , content_url,content_date,sg , zf , pl , dz ])
            
        # 输出当前页码
        try:
            t = browser.find_element_by_xpath('//a[@class="pagenum"]')
            print('扫描进行到',str(t.text))
        except :
            pass
        # 判断是否还有下一页
        #break
        try:
            t = browser.find_element_by_xpath('//div[@class="m-page"]/div/a[@class="next"]')
            # 点击下一页
            t.click()
        except:
            print('文章扫描结束')
            break
    except Exception as e:
        print('非正常结束:',str(e))

2.2将数据暂存到excel

%%time
# 保存发表的文章,到excel
df = pd.DataFrame(list_ct, columns=['actor_url' , 'actor_name' , 'content' , 'content_url','content_date','sg' , 'zf','pl','dz']) 
# 去重
df.drop_duplicates(subset=['actor_url' , 'actor_name' , 'content' , 'content_url','content_date','sg' , 'zf','pl','dz'],inplace = True)
with pd.ExcelWriter(r'../data/npl_asan/wenzhangs.xlsx') as writer:
    df.to_excel(writer,index=False,sheet_name = 'Sheet1')

3、通过博文链接,进入到博文主页,分析页面信息,内容需要ajax异步更新,1、需要不断下拉进度条到底部刷新,并点击“查看更多”;2、某些评论回复的会折叠,需要不断点击查看更多评论。综上所述,先下拉到最底部,再逐个点击评论显示,最后读取所有评论。

#
#  处理评论的内容
#
def deal_comment_content(content):
    rel = content = content.replace(":",":")
    if content.find(':回复') != -1:
        lt = content.split(':',2)
        rel = lt[len(lt)-1]
    else:
        lt = content.split(':',1)
        rel = lt[len(lt)-1]
    return rel

# 获取WB_text内容
def get_comment_data(l):
    actor = actor_url = render = render_url = content = date =  ''
    # 获取发表者
    t = l.find_element_by_xpath('./div[@class="WB_text"]/a[1]')
    actor_url = t.get_attribute('href')
    actor = t.text

    # 判断是否回复的评论
    try:
        t = l.find_element_by_xpath('./div[@class="WB_text"]/a[@render="ext"]')
        render_url = t.get_attribute('href')
        render = t.text
    except NoSuchElementException:
        pass

    # 读取评论内容
    t = l.find_element_by_xpath('./div[@class="WB_text"]')
    content = t.text
    content = deal_comment_content(content)
    
    # 读取评论日期
    t = l.find_element_by_xpath('./div[@class="WB_func clearfix"]/div[@class="WB_from S_txt2"]')
    date = t.text
    
    return [actor , actor_url , render , render_url , content,date]

# 滚动到最底部
def scroll_down():
    while True:
        sh1 = browser.execute_script("return document.body.scrollHeight;")
        browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
        time.sleep(0.5)
        sh2 = browser.execute_script("return document.body.scrollHeight;")
        
        if sh1 == sh2: 
            break

# 加载更多评论
def loading_all_comment():
    # 执行到最下,等待查看更多
    while True:
        scroll_down()
        try:
            morr_btn = wait.until(EC.presence_of_element_located((By.XPATH,'//span[@class="more_txt"]')))
            # 如果超时
            morr_btn.click()
        except:
            #print('执行到最底部')
            break

# 载入所有子评论
def loading_all_child_comment():
    while True:
        btns = browser.find_elements_by_xpath('//a[@action-type="click_more_child_comment_big"]')
        if len(btns) == 0:
            break
        for btn in btns:
            try:
                #browser.execute_script("arguments[0].click();", btn)
                ActionChains(browser).move_to_element(btn).click(btn).perform()  # 需要移动到该控件,点击才有效
                #btn.click()
                time.sleep(0.5)
            except:
                # 存在点了以后还没加载完的,直接忽略错误
                pass
%%time
# 完整版执行
err_url = []
list_comment = []
for index, r in df.iterrows():
    url = r.content_url
    #url = df.loc[2,'content_url']
    print('序号:',str(index),'开始执行:',url)
    browser.get(url)
    try:
        loading_all_comment()  # 载入所有评论
        loading_all_child_comment()  # 载入所有子评论
        print('打开所有评论')
        #等待内容
        wait.until(EC.presence_of_element_located((By.XPATH,'//div[@node-type="root_comment"]/div[@class="list_con"]')))
        list_el = browser.find_elements_by_xpath('//div[@node-type="root_comment"]/div[@class="list_con"]')
        # 遍历
        for l in list_el:
            # 获取博文信息
            c = get_comment_data(l)
            list_comment.append(c)
            # 获取博文评论信息
            list_child = l.find_elements_by_xpath('.//div[@node-type="child_comment"]//div[@class="list_con"]')
            for lc in list_child:
                c = get_comment_data(lc)
                list_comment.append(c)
    except TimeoutException:
        print('TimeoutException:',url)
    except NoSuchElementException:
        print('NoSuchElementException:',url)
    except:
        print('something wring:',url)
        err_url.append(url)
    #break

最后输出到文件:

%%time
# 保存评论到excel
df = pd.DataFrame(list_comment, columns=['actor' , 'actor_url' , 'render' , 'render_url' , 'content' , 'date']) 
# 去重
df.drop_duplicates(subset=['actor' , 'actor_url' , 'render' , 'render_url' , 'content' , 'date'],inplace = True)
with pd.ExcelWriter(r'../data/npl_asan/comments.xlsx') as writer:
    df.to_excel(writer,index=False,sheet_name = 'Sheet1')

本篇到此结束,下篇再做数据处理。

不足:没有使用代理,也没有使用cookies池,需要注意sleep,不知道达到什么情况会被封号;

Wall time: 1h 34min 57s,最终534条博文+6626条子评论,耗时也不少。有多机子可以考虑使用分布式爬虫。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python selenium 微信公众号历史文章随手一点就返回首页?郁闷之下只好将他们都下载下来。

    参照资料:selenium webdriver 如何添加cookie: https://www.cnblogs.com/sundahua/p/10202494....

    forxtz
  • 配置 myeclipse 一点点

    在 myeclipse \MyEclipse 10 myeclipse.ini 末行添加

    forxtz
  • 记一次 excel vba 参考手册爬虫实战,不必要的一次爬虫。

    目的:基于办公与互联网隔离,自带的office软件没有带本地帮助工具,因此在写vba程序时比较不方便(后来发现07有自带,心中吐血,瞎折腾些什么)。所以想到通过...

    forxtz
  • 初识SignalR~仿QQ即时聊天(群发,单发)(Web,WPF等Demo演示)【中】

    第二个阶段: QQ聊天案例,先讲一种常规的方法,下面会讲一种简单方法 先看看gif效果图把 ? 定义一个BaseHub类,里面用 qqModeList来...

    逸鹏
  • zephir-(5)类型

    #zephir-类型# ? ##前言## 先在这里感谢各位zephir开源技术提供者 Zephir既可以使用动态类型也可以使用静态类型,这是zephir独特的一...

    喵了个咪233
  • 简单的导航网站制作

    这里简单地介绍一下制作一个简易导航网站的主要方法。在这之前要说一下为什么要自己制作导航网站,现在网络上有许多各种各样的导航网站,但是网络上的导航网站大多商业化比...

    用户1506126
  • CRM客户关系管理系统(五) 第五章、分页功能开发

    zhang_derek
  • 一篇文带你从0到1了解建站及完成CMS系统编写

    文章为从0到1了解内容管理系统搭建与编写,由于一篇文章内容篇幅过长,文章内容经过压缩,该项目中相同逻辑的实现只以一个实例作为描述,主要以核心关键功能的开发作为主...

    公众号 碧油鸡
  • tkinter -- Canvas(3)

    scale 缩放 item,计算公式:(coords - offset)*scale + offset

    py3study
  • 怎么在vue的style标签里面使用变量?

    兄弟,我刚好碰到这个问题。代码里需要不断变更CSS里样式的值(遍历+大量),并通过JS进行设置。基本上要求应该是和你差不多的。 以上所有方法我基本都试过,用了...

    stys35

扫码关注云+社区

领取腾讯云代金券