python金融大数据挖掘与分析——新闻数据挖掘

落花浮王杯 提交于 2020-01-30 23:46:48

1. 提取百度新闻标题、网址、日期及来源

1.1 获取网页源代码

我们通过如下代码可以获取网页源代码,示例中代码是获取在百度新闻中搜索阿里巴巴的网页源代码。

import requests

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                             'AppleWebKit/537.36 (KHTML, like Gecko) '
                             'Chrome/77.0.3865.120 Safari/537.36'}
res = requests.get(url, headers=headers)
web_text = res.text

因为百度新闻网站只认可浏览器发送的请求,所以需要设置headers参数,以模拟浏览器的发送请求,chrome浏览器可以通过about:version获取。

1.2 编写正则表达式提取新闻信息

1.2.1 提取新闻的来源和日期

在这里插入图片描述
通过观察网页源码,我们发现每条新闻的来源和发布日期都夹在

之间,因此,可以通过正则表达式获取中间的来源和日期信息。
pattern = '<p class="c-author">(.*?)</p>'
info = re.findall(pattern, web_text, re.S)      # re.S用于考虑换行符,因为.和*不包含换行符
print(info)

获取的信息中包含了很多诸如空格、换行符、制表符以及标签的内容,需要对数据进行二次清洗,这部分内容将在后面章节介绍到。

1.2.2 提取新闻的网址和标题。

为了提取新闻网址和标题,需要像上节那样从网页源码中发现规律,通过获取的源码,我们发现,新闻地址前面都有


在这里插入图片描述
通过如下两段代码,可以分别获取新闻的网址和标题。

    pattern_herf = '<h3 class="c-title">.*?<a href="(.*?)"'
    herf = re.findall(pattern_herf, web_text, re.S)
    print(herf)

    pattern_title = '<h3 class="c-title">.*?>(.*?)</a>'
    title = re.findall(pattern_title, web_text, re.S)
    print(title)

获取的数据同样需要进行二次数据清洗。

1.2.3 数据清洗

  1. 新闻标题清洗
    提取的新闻标题数据存在两个问题:一是每个标题的收尾含有换行符和一些空格;二是中间含有等无效字符。

(1)通过stip()函数把不需要的空格和换行符去掉。

for i in range(len(title)):
    title[i] = title[i].strip()

(2)用sub()函数处理

for i in range(len(title)):
    title[i] = title[i].strip()
    title[i] = re.sub('<.*?>', '', title[i])
  1. 新闻来源和日期清理
    提取的新闻来源和日期中存在的问题:夹杂着很多标签信息;新闻来源和日期连在一起;夹杂着很多换行符、制表符、空格符等
    for i in range(len(info)):
        info[i] = re.sub('<.*?>', '', info[i])            # 清洗<img>标签信息
        source.append(info[i].split('&nbsp;&nbsp;')[0])   # 将新闻来源和日期分开
        date.append(info[i].split('&nbsp;&nbsp;')[1])
        source[i] = source[i].strip()
        date[i] = date[i].strip()

2. 批量获取多家公司的百度新闻并生成数据报告

本章主要实现批量获取多家公司的信息,并自动生成数据报告,导出为一个文本文件

2.1 批量爬取多家公司的百度新闻

这里,我们将爬取网页的工作封装成一个函数。

def baidu_news(company):
    """
    获取网页源码,并提取百度新闻标题、网址、日期和来源
    :param company: 公司名称
    :return: 网页源码
    """
    url = 'https://www.baidu.com/s?rtt=1&bsst=1&cl=2&tn=news&word=' + company
    # 百度新闻网站只认可浏览器发送的请求,所以需要设置headers参数,
    # 以模拟浏览器的发送请求,chrome浏览器可以通过about:version获取
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                             'AppleWebKit/537.36 (KHTML, like Gecko) '
                             'Chrome/77.0.3865.120 Safari/537.36'}
    res = requests.get(url, headers=headers)
    web_text = res.text

    # 获取新闻的来源和日期
    pattern = '<p class="c-author">(.*?)</p>'
    info = re.findall(pattern, web_text, re.S)  # re.S用于考虑换行符,因为.和*不包含换行符
    # print(info)

    # 获取新闻的网址和标题
    pattern_herf = '<h3 class="c-title">.*?<a href="(.*?)"'
    herf = re.findall(pattern_herf, web_text, re.S)
    # print(herf)

    pattern_title = '<h3 class="c-title">.*?>(.*?)</a>'
    title = re.findall(pattern_title, web_text, re.S)
    # print(title)

    # title 数据清洗
    for i in range(len(title)):
        title[i] = title[i].strip()
        title[i] = re.sub('<.*?>', '', title[i])

    # print(title)

    # 新闻来源和日期清洗
    source = []
    date = []

    for i in range(len(info)):
        info[i] = re.sub('<.*?>', '', info[i])  # 清洗<img>标签信息
        source.append(info[i].split('&nbsp;&nbsp;')[0])  # 将新闻来源和日期分开
        date.append(info[i].split('&nbsp;&nbsp;')[1])
        source[i] = source[i].strip()
        date[i] = date[i].strip()

        print(str(i+1) + '.' + title[i] + '(' + date[i] + '-' + source[i] + ')')

然后再主函数中编写调用过程。

    companys = ['华能信托', '腾讯', '阿里巴巴']
    for company in companys:
        baidu_news(company)
        print(company + '百度新闻爬取成功')

结果如下所示:

1.信托业绩哪家强?两家去年净利超30亿 华宸华融有点“惨淡”(2020012123:38-每日经济新闻)
2.57家信托业绩哪家强?中信、华能、重庆信托稳坐前三(2020012007:47-新浪财经)
3.2019年净利润排位确定:中信信托35.93亿独占鳌头(2020011616:51-金融界)
4.关于为“华能信托-链融科技诚意2期供应链金融资产支持专项计划”...(2020011623:10-金融界)
5.2019信托公司业绩哪家强?(2020011719:53-中国金融新闻网)
6.去年信托调研185家上市公司 电子设备制造业成为重点(2020010610:07-中国基金会网)
7.关于为“华能信托-一方诚意3期供应链金融资产支持专项计划”提供...(2020010623:10-新浪)
8.牧原股份联合华能信托 拟72亿元设立两家养猪子公司(2019121122:28-同花顺财经)
9.牧原股份生猪养殖多地开花 借力华能信托找钱(2019121110:32-财新)
10.牧原股份(002714.SZ)与华能贵诚信托设立的合资公司已注册成立(2019121221:09-新浪)
华能信托百度新闻爬取成功
1.广东首例N95口罩诈骗案告破 腾讯协助警方破案(1小时前-中国新闻网)
2.抗击疫情 腾讯联合微医等五平台提供义诊服务(1小时前-新浪)
3.腾讯联合五大平台,在线义诊新型肺炎(1小时前-手机凤凰网)
4.腾讯文档开放免费会员,全面支持远程办公(4小时前-新浪)
5.最惨游戏工作室!139款神作却穷得叮当响,腾讯看中后出手了(1小时前-17173游戏网)
6.音乐战“疫”进行时 TME腾讯音乐人踊跃创作公益歌曲“声”援武汉(54分钟前-腾讯科技)
7.如果说国行NS不是腾讯和任天堂合作的重点,那什么是重点?(1小时前-新浪)
8.腾讯云向黄牛教授实验室,罗海彬教授团队提供免费云超算等(23分钟前-钛媒体)
9.停课不停学 腾讯课堂助力重庆十一中高三线下课首次线上开课(6小时前-环球网)
10.腾讯文档开放免费会员功能 协同编辑人数至200(50分钟前-中关村在线)
腾讯百度新闻爬取成功
1.阿里巴巴全球14国直采医疗物资驰援,将通过东方航空陆续抵汉(39分钟前-武汉发布)
2.阿里巴巴全球采购医疗物资 首批N95口罩今日运抵武汉(29分钟前-浙江新闻)
3.阿里巴巴与东航合力 在14国采购与运输医疗物资(1小时前-新浪)
4.阿里巴巴全球采购医疗物资陆续抵沪(48分钟前-同花顺财经)
5.阿里巴巴一纸“禁令”后,商家祭出高仿口罩!抓住这点、一招鉴别(9分钟前-IT爆料王)
6.阿里巴巴等百家企业承诺:防疫、民生用品价格不涨(6小时前-TechWeb)
7.【阿里巴巴等多个企业共同发出“三保行动 让我们一起出发”的倡议】(5小时前-新浪)
8.阿里巴巴上线发热门诊查询 已覆盖5734个发热门诊(2020012911:10-中国新闻网)
9.武汉疫情口罩脱销,阿里巴巴发出紧急通知,这种口罩不能买!(1小时前-科技季节)
10.阿里巴巴等多家企业响应市场监管总局“三保”行动(2020012923:47-新浪财经)
阿里巴巴百度新闻爬取成功

2.2 自动生成舆情数据报告文本文件

上一节已经爬取到了我们想要的新闻,并生成了舆情结果,下面将其导出到文本文件中。
在baidu_news()函数后面增加导出到文件的相关操作代码如下:

    file_ = open('数据挖掘报告.txt', 'a')     #追加模式,不清除原来的数据
    file_.write(company + '新闻数据:' + '\n' + '\n')
    for i in range(len(title)):
        file_.write(str(i+1) + '.' + title[i] + '(' + date[i] + '-' + source[i] + ')' + '\n')
        file_.write(href[i] + '\n')

    file_.write('————————————————————————————————————————————' + '\n' + '\n')
    file_.close()

3. 异常处理及24小时实时数据挖掘实战

3.1 异常处理

这里需要对函数baidu_news()的执行进行异常处理。

    companys = ['华能信托', '腾讯', '阿里巴巴']
    for company in companys:
        try:
            baidu_news(company)
            print(company + '百度新闻爬取成功!')
        except:
            print(company + '百度新闻爬取失败!')

3.2 24小时实时爬取

这个功能的实现比较简单,只需要在程序外面套一层while True循环即可,然后可以在每一次循环执行之后,引用time库,执行time.sleep()函数来让程序每隔一段时间执行一次。
通过前面的代码,我们已经能够实现24小时不间断获取新闻内容,但是这里面不可避免的会爬取到重复的新闻数据,这就涉及到数据去重的内容,需要用到数据库的相关知识,这部分内容将在后面的章节进行介绍,感兴趣的读者可以继续关注。

4. 按时间顺序爬取及批量爬取多页内容

前面的章节仅仅是爬取了百度新闻搜索结果的第一个页面的内容,消息数据不全面,本章将会介绍批量爬取多页内容的方法。

4.1 按时间顺序爬取百度新闻

这里不涉及代码修改的内容,因为百度新闻默认是按照“按焦点顺序”排列新闻内容,这里我们可以在搜索结果页面的右上角选择“按时间排序”按钮,然后修改一下url即可。

4.2 一次性批量爬取多页内容

如果要实现爬取多页内容,我们需要分析每一页网址的差别。
第一页内容的网址为。

https://www.baidu.com/s?tn=news&rtt=1&bsst=1&cl=2&wd=阿里巴巴

第二页内容的网址为。

https://www.baidu.com/s?tn=news&rtt=1&bsst=1&cl=2&wd=阿里巴巴&pn=10

第二页内容的网址为。

https://www.baidu.com/s?tn=news&rtt=1&bsst=1&cl=2&wd=阿里巴巴&pn=20

通过对比可以发现,页面网址之间的差别就在&pn=XX,这里可以确定第一页的网址后面可以加上内容&pn=0,因此,可以对代码进行如下修改。

def baidu_news(company, page):
    """
    获取网页源码,并提取百度新闻标题、网址、日期和来源
    :param company: 公司名称
    :param page: 需要爬取的页面的数量
    :return: 网页源码
    """
    num = (page - 1) * 10

    url = 'https://www.baidu.com/s?rtt=1&bsst=1&cl=2&tn=news&word=' + company + '&pn=' + str(num)

    res = requests.get(url, headers=headers, timeout=10)
    web_text = res.text
    # 此处省略了数据提取、清洗和爬取的代码

def main():
    companys = ['华能信托', '腾讯', '阿里巴巴']
    for company in companys:
        for i in range(5):      # 爬取5页内容
            try:
                baidu_news(company, i+1)
                print(company + str(i+1) + '页新闻爬取成功!')
            except:
                print(company + str(i+1) + '页新闻爬取失败!')

5. 搜狗新闻与新浪财经数据挖掘实战

这里采取的方法与爬取百度新闻的方法类似。

5.1 搜狗新闻数据爬取

  1. 首先获取搜狗新闻的网址,我们在搜狗新闻中搜索“阿里巴巴”,获得网址为(经过删减):

https://news.sogou.com/news?query=阿里巴巴

  1. 完整代码如下:
"""
    作者:Aidan
    时间:30/01/2020
    功能:爬取搜狗新闻数据
"""

import requests
import re

# 百度新闻网站只认可浏览器发送的请求,所以需要设置headers参数,
# 以模拟浏览器的发送请求,chrome浏览器可以通过about:version获取
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                         'AppleWebKit/537.36 (KHTML, like Gecko) '
                         'Chrome/77.0.3865.120 Safari/537.36'}

def sougou_news(company, page):
    """
    获取网页源码,并提取搜狗新闻标题、网址、日期和来源
    :param company: 公司名称
    :param page: 需要爬取的页面的数量
    :return: 网页源码
    """

    url = 'https://news.sogou.com/news?query=' + company + '&page=' + str(page)

    res = requests.get(url, headers=headers, timeout=10)    # 当访问网址10秒没有响应时,就会停止访问。timeout=10
    web_text = res.text

    # 获取新闻日期
    pattern_date = '<p class="news-from">.*?&nbsp;(.*?)</p>'
    date = re.findall(pattern_date, web_text, re.S)  # re.S用于考虑换行符,因为.和*不包含换行符
    # print(info)

    # 获取新闻的网址和标题
    pattern_herf = '<h3 class="vrTitle">.*?<a href="(.*?)"'
    href = re.findall(pattern_herf, web_text, re.S)
    # print(href)

    pattern_title = '<h3 class="vrTitle">.*?>(.*?)</a>'
    title = re.findall(pattern_title, web_text, re.S)
    # print(title)

    # 数据清洗
    for i in range(len(title)):
        title[i] = re.sub('<.*?>', '', title[i])
        title[i] = re.sub('&.*?;', '', title[i])
        date[i] = re.sub('<.*?>', '', date[i])

    file_ = open('搜狗数据挖掘报告.txt', 'a')     #追加模式,不清除原来的数据
    file_.write(company + str(i+1) + '页新闻数据:' + '\n' + '\n')
    for i in range(len(title)):
        file_.write(str(i+1) + '.' + title[i] + '(' + date[i] + ')' + '\n')
        file_.write(href[i] + '\n')

    file_.write('————————————————————————————————————————————' + '\n' + '\n')
    file_.close()

def main():
    companys = ['华能信托', '腾讯', '阿里巴巴']
    for company in companys:
        for i in range(5):      # 爬取5页内容
            try:
                sougou_news(company, i+1)
                print(company + str(i+1) + '页新闻爬取成功!')
            except:
                print(company + str(i+1) + '页新闻爬取失败!')

if __name__ == '__main__':
    main()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!