以话题关键词采集推特

使用自动化测试工具 Selenium 实现自动访问推文检索页面并滚动到页面最底,等待网页动态加载完成之后保存成 .html 文件,来收集对应月份对应 hashtag 的推文。

存储格式是新建 crawl 文件夹,其中包含以每个 hashtag 命名的子文件夹,子文件夹中存放推文的 html 数据,命名为 201601、201602 等,六位字符串。如下。

└─crawl
├─#hashtag1
│ 201601
│ 201602
│ 201603

└─#hashtag2
201601
201602
201603

Selenium 的运行需要浏览器驱动的支持,在这里使用了 Chrome 驱动来加载,并且设置禁止所有 Flash、声音、图片等内容,加快进度。

需要抓取的 hashtag 放在一个文件中,程序每次读取一个 hashtag,然后遍历需要收集的月份,每次新的请求 URL 都通过字符串拼接的方式完成。一个请求的 URL 格式如下:

https://twitter.com/search?l=en&q=%23brexit%20since%3A2016-01-01%20until%3A2016-01-31&src=typd

每次只需更改 q= 关键字,since 和 until 起止时间。

采集脱欧相关的新闻文章

BrexitNews 收集

利用 scrapy 框架爬取英国和其他国家主要媒体 DailyMailDailyStarEconomistExpressFTiNewsMirrorThe GuardianThe Sun 等,在 2016 年 6 月 16 日—2016 年 6 月 24 日期间(公投前一周)的有关脱欧话题的新闻稿。

所记录的域包含新闻标题、发表日期、正文内容、发表媒体等。

得到总共 2000 多篇新闻稿。(最终结果中仅使用300余篇)

标记新闻

选取一些新闻语料进行人工标记判断,是留欧还是脱欧派的新闻。有一些倾向性模糊的语料废弃,不加入训练。一些文章可按段落拆解,一部分段落是留欧倾向,一部分则相反。

新闻分类

可使用 FastText 或按照 hashtag 中所述的 SVM 的方法对新闻进行二分类。

然后对每家媒体的每一篇新闻稿做出预测,可以估计出一家媒体的观点倾向。从结果来看,留欧倾向比较明显的媒体是 theguardian,脱欧倾向比较明显的是 dailymail,其余介于两者之间。

关键词提取

同 hashtag 中倾向性的刻画。不同的是 hashtag 中需要做分析的特征是我们指定的若干 hashtag,而在此处需要分析的特征是出现在这些新闻中的所有单词。

计算话题的脱欧倾向性

目的

输出选定的 hashtag 集合的倾向性数值 x,范围 0<=x<=1

1 表示完全脱欧倾向,0 表示完全留欧倾向。越靠近 1 代表脱欧倾向越明显,越靠近 0 留欧倾向越明显。靠近 0.5 的可以认为是中立。

1. 抓取原始数据

抓取 2016 年 1 月至 2019 年 5 月的推文数据。刚开始在 #brexit#referendum 的“热门”分类下收集推文,但是发现一个有意思的事情——收集到的有关 #strongerin 的推文都和预计的正好相反,这本来应该是一个强留欧的话题,但混入了大量的脱欧派言论。许多推文甚至说的完全就是脱欧的观点,打了其他许多脱欧的标签,然后加上一个 #strongerin。猜测原因是脱欧派会去干扰其他留欧民众所讨论的话题,这一点未经验证。

最后,按照所需要的 hashtag 来抓取每个月的推文数据,其详细方法见项目下的 collect。(还可以使用推特开发者账户API来获取原始推文,需国外手机号。)

2. 标记数据

构建分类模型首先需要训练数据,需要一些已经标记好“留欧”还是“脱欧”观点的推文。但是,传统的通过人工的方法难以在短时间完成标记。所以在这里,我们用了预定义分类标签的方法。

其中有一些 hashtag 是带有很的强烈情感倾向的,不需要特别判断其他内容就能了解这一段推文的倾向。例如,带有 #voteleave 话题的推文,几乎可以肯定说的是脱欧。

因此,我们将带有以下话题的推文预先打上脱欧的标记:#voteleave,#marchtoleave,#takecontrol,#leaveeu,#standup4brexit,#no2eu,#nodeal。将带有以下话题的推文预先打上留欧的标记:#voteremain,#peoplesvotemarch,#bremain,#remainernow,#abtv,#yeseu,#strongerin。根据我们的验证,这一步中话题的选取是比较关键的,会直接影响最后生成的数值,需要仔细斟酌。最后生成的代表两派的推文数量有所差别,随机选取相等数量的推文作为正负两类的训练数据。

3. 构建分类器模型

利用 SVM 分类模型对抓取到的所有推文进行“脱欧VS留欧”的二分类。

首先需要对原始的推文进行清洗,删去超链接、非英文字符等,然后统一格式化成两个单词中包含一个空格的形式,最后转成英文小写。数据的清洗对于结果也至关重要,可以去除一些无用的语义信息。

利用 TF-IDF 来抽取特征信息,分析器使用“词语”,词的模式 token_pattern 用正则表达式 r'[a-z|\#]\w+\b' 表示,意思是字母或 # 开头的,后跟一个或多个非空字符直到单词边界,最小计数可自行尝试。(亦可使用 doc2vec 等词嵌入的方法进行向量化,但速度稍慢)

最后把向量化标记好的正负两类数据输入到 SVM 分类模型中,学习出一个能够分类脱欧还是留欧倾向推文的分类器。使用线性核,C 惩罚值根据验证集的表现可做调整。最后分类精度在验证集上能够达到 0.95 的准确率。

将收集到的所有推文输入到 SVM 分类器中进行二分类,得分类完成的正反两类推文。

4. 刻画倾向值

朴素贝叶斯 是一种基于概率的模型,能够输出指定条件下是某一分类的概率。用 sklearn 库下的 feature_log_prob_ 来输出指定类的各特征的概率。他的计算是 feature_log_prob_ = ln(某类下某属性中某值出现的次数 + alpha) / (某类下所有特征出现次数之和 + 类的个数 * alpha)),其中 alpha 是拉普拉斯平滑系数。比较两类的每个 hashtag 的特征概率值,可以算出某个特征(hashtag)倾向于某类的特征。

使用多项式贝叶斯,设置参数不学习先验概率,重新用前面分完类的所有数据当成已知标签的数据,构造贝叶斯模型。最后可以生成每一个 hashtag 所对应的倾向性分值。

相关文件

  • is_leave.py:根据预定义的标签生成带标记的训练数据。
  • build.py:训练和构建分类模型,生成 models 文件夹,存放模型。输出验证集精度。
  • classify.py:将 tweets 文件夹中的推文分类,生成 classifier_result 文件夹,存放结果。
  • evaluate.py:利用分类完成的结果,构建贝叶斯,输出每个 hashtag 评价。

参考资料

[1] Lopez J C A D , Collignon-Delmar S , Benoit K , et al. Predicting the Brexit Vote by Tracking and Classifying Public Opinion Using Twitter Data[J]. Statistics, Politics and Policy, 2017, 8(1).

脱欧话题走势

​ 2013年1月23日,英国首相卡梅伦首次提及脱欧公投。在2016年2月欧盟峰会后,确定宣布英国于2016年6月23日举行,脱欧阵营以51.9%对留欧阵营48.1%的微弱优势取胜,脱欧拉锯战也自此开始。2019年1月,英国议会下院投票否决了此前英国政府与欧盟达成的脱欧协议。3月,修改后的脱欧协议仍然没有通过。4月,欧盟各国达成一致,同意将脱欧日期延迟至2019年10月31日。

​ 同样的,在过去三年中,脱欧也是社交网络上被频繁讨论的话题之一。在推特上,不同立场的讨论者会使用不同的hashtag(类似于微博的话题,后文以话题表示)来表明自己的阵营,或者以话题标签来表明所讨论的主题事件等。因此,本文以推特中脱欧相关的话题作为研究对象,来作为对脱欧事件民众意见及热点事件分析的切入点。

​ 下图为脱欧话题动态,横轴为话题的讨论量(包含特定话题的推文数量),纵轴为话题的支持量(包含特定话题的推文转发数量)。图中显示的是2016年6月的各类话题的讨论量与支持量。

脱欧话题走势 (截自动画)

​ 我们一共统计2016年1月至2019年5月,共计41个月的话题走势。具体的可视化动态呈现在该网页,代码可于该仓库获取。其中,红色的话题代表支持脱欧话题,灰色为中立话题,蓝色为支持留欧的话题,该倾向值的计算方式可参考该文章

​ 下面将结合代码详细介绍话题数据如何使用Python 3获取数据,清理,并进一步分析获取结果。

数据来源

  • 201601 至201905 包含特定hashtag的推特 Top 分类推文,以月为单位

    Top分类是指网页版推特在检索时的该页面

分析工具

  • Python 3.6.5
  • 使用到的库:NumPy, Re, BeautifulSoup, selenium

数据获取及分析过程

安装chrome及chromedriver

  1. 在官网下载chromedriver,需要与已安装的chrome的版本对应,下载地址为: http://chromedriver.storage.googleapis.com/index.html

  2. 将chromedriver的安装路径粘贴到系统变量中(参考python的环境变量配置)

  3. 在终端中输入 chromedriver —version检查是否配置成功

    检查 chromedriver 配置是否完成

安装需要的Python包

  • 如果本机已安装pip( Python 3.4+ 以上版本都自带 pip 工具),则直接在终端运行以下两条命令安装BeautifulSoup 和 selenium包。

    pip install beautifulsoup4

    pip install selenium

  • 若本机未安装pip,可参考该教程安装pip并了解如何使用pip进行包管理。另外,easy_install 等包管理工具也可用于安装所需的包。

获取github代码

  • 在终端中执行

    git clone https://github.com/BrexitProject/TweetsMining.git

    git 的详细命令可参考该教程

  • 也可以在网页中直接选择download zip, 获得代码压缩包。

执行代码获取相关数据

​ 相关代码在 TweetsMining/collect/ 中获取。

  1. 在view.py文件中设置起始月份(start变量)与结束月份(stop变量),格式为YYYYMM。

    日期设置

  2. 在tag文件中按行添加需要进行统计的话题,如:

    hashtag添加

  3. 获取包含推文和转推量信息的html文件。执行view.py,会弹出chrome浏览器,则表明程序正在执行。使用者可以看到chrome网页正在自动下拉加载新的推特,直至网页底部。

    • 在网页加载完毕后,需人工确认网页是否加载完毕,确认后程序继续执行,加载新网页。这是由于国内连接推特需翻墙,若连接不稳定,可能旧网页未加载完毕时就会开始加载新网页。

      若有需要,可在view.py中删去该行,则无需人工确认网页是否加载完毕:

      1
      tkinter.messagebox.showinfo('提示', '确认网页加载完成?')

    执行完毕后,将得到一个新文件夹crawl,文件夹中有多个以话题命名的子文件夹,子文件夹中有多个以月份命名的html文件。这些html文件中包含了推文的文本内容,发推者,发推时间,推文转发量,推文点赞量等信息。

    保存的html文件

  1. 执行function.py,程序执行完毕后将获得两个csv文件,分别为tweet_data,retweet_data。其格式及内容如图:

    tweet_data示例

    之后的可视化步骤所使用的就是此处得到的数据。

  2. 若有需要,执行getTweets.py可获取每个html文件中的推文文本。

文中涉及的所有代码都可以在该 github 仓库 中获取。