前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python: 从新闻中快速搜索特定股票名称

Python: 从新闻中快速搜索特定股票名称

作者头像
用户7652506
发布2022-01-07 15:39:15
8840
发布2022-01-07 15:39:15
举报
文章被收录于专栏:大猫的R语言课堂

问题提出

上次村长介绍了如何快速在新闻中搜索特定词条的方法。这个问题在经济和金融学研究中非常常见:给定一组新闻标题和股票名称,我们想知道每个股票在这些新闻标题中分别出现多少次。村长的解决办法使用的是 R 和 JiebaR,这里大猫给出用 Python 的解法。

先来看一下数据集。首先我们有news数据集,它保存着新闻 ID 和新闻标题:

代码语言:javascript
复制
news[:3,:]

NewsID

Title

▪▪▪▪

▪▪▪▪

0

57285603

富机达能正式挂牌

1

57463469

新能源过剩事出有因 多晶硅风电获准松绑

2

57463473

近9年元旦后首个交易日沪指走势一览 虎年怎开盘

3 rows × 2 columns

其中,NewsID是新闻 ID,而Title就是我们要搜索的新闻标题。为了方便后面处理,我们把NewsIDTitle分别新建为两个独立的 list,命名为news_idnews_title

代码语言:javascript
复制
print(f'news_id: {news_id[:3]}')
print(f'news_title: {news_title[:3]}')
代码语言:javascript
复制
news_id: [57285603, 57463469, 57463473]
news_title: ['富机达能正式挂牌', '新能源过剩事出有因 多晶硅风电获准松绑', '近9年元旦后首个交易日沪指走势一览 虎年怎开盘']

第二个需要用到的股票列表stock_name,它保存着所有需要检索的股票名称:

代码语言:javascript
复制
print(f'stock_name: {stock_name[:3]}')
代码语言:javascript
复制
stock_name: ['平安银行', '万科A', '国农科技']

最终效果

最终生成的结果如下。其中stock是股票名, news是对应的股票名所在的新闻标题,news_id是对应的新闻 ID。需要注意,对于同一个股票名,我们可能会成功匹配多条新闻。

stock

news_id

news

▪▪▪▪

▪▪▪▪

▪▪▪▪

0

三力士

57464083

浙江三力士橡胶股份有限公司关于产品提价的公告

1

东方园林

57464009

北京东方园林股份有限公司关于使用超募资金偿还银行贷款及补充流动资金的公告

2

中国人寿

57464089

中国人寿保险股份有限公司关于执行《保险合同相关会计处理规定》的提示性公告

3 rows × 3 columns

解法 1:正则表达式(只找第一个匹配)

我们使用正则表达式来进行字符串匹配。在第一种解法中,我们只寻找新闻标题中出现的第一个股票。举个例子,假如我们的新闻标题是

平安银行中国人寿公布第三季度财报 ”

那么这种方法只能找到标题中出现的第一个股票,也就是平安银行。在解法 2 中,我们会给出如何标题中出现所有股票的方法。

在进行所有操作之前,我们需要对股票名称进行清洗。我们知道,有些股票名前可能会带有“*”,比如*st 康达。在正则表达式中,_是一个特殊字符,表示是“匹配0次或任意次”。因此我们需要把_从股票名中删去。最终生成清洗过的股票名列表stock_name_clean

代码语言:javascript
复制
stock_name_clean = [s.replace('*','') for s in stock_name]

print(f'stock_name_clean: {stock_name_clean[:3]}')
代码语言:javascript
复制
stock_name_clean: ['平安银行', '万科A', '国农科技']

接下来我们正式进行正则匹配。解法的核心是把候选的股票名称变成一个正则表达式能够接受的 pattern。在正则表达式中,竖杠 “|” 用来表达“或”。所以我们只需要用竖杠把所有的候选股票名连起来:

代码语言:javascript
复制
import re

pattern = re.compile('|'.join(stock_name_clean))

print(f'pattern: {pattern}')
代码语言:javascript
复制
pattern: re.compile('平安银行|万科A|国农科技|世纪星源|深振业A|全新好|神州高铁|中国宝安|ST美丽|深物业A|南玻A|沙河股份|深康佳A|深中华A|ST神城|深粮控股|深华发A|深科技|深天地A|特力A|飞亚达A|深圳能源|国药一致|深深房A|富奥股份|大悦城|深桑达A|神州数码|中国天楹|华联控股|深南电A|深大通|中集集团|东旭蓝天|中洲控股|中航善达|深纺织A|泛海控股|ST康达|德赛电池|深天马A|方)

其中,pattern就是正则表达式要匹配的模式。我们这里使用了re.compile预先编译模式,这样在接下来的循环中就不需要一次次重复编译模式了,大大增加了效率。

接下来我们使用一个循环来从每一条新闻标题中寻找股票名。我们使用search这个函数:

代码语言:javascript
复制
import datatable as dt
import pandas as pd

# results 用来保存最终结果
results = []

for id, title in tqdm(zip(news_id[:8], news_title[:8])):

    # stock 是匹配的结果,如果匹配失败为None,如果匹配成功则为一个"re.Match"对象
    stock = pattern.search(title)

    # 如果结果不为None,那么保存结果
    if stock:
        results.append((stock.group(), id, title))

# 尝试打印结果的前三行
# 这里大猫使用了datatable包。如果读者使用pandas,那么就注销此条语句,并执行下一条
dt.Frame(results, names=['stock', 'news_id', 'news'])[:,:,dt.sort(f.stock)][:3,:]

# 如果使用pandas,则执行下面语句:
# pd.DataFrame(results, columns=['stock', 'news_id', 'news'])[:3]
代码语言:javascript
复制
8it [00:00, 3859.94it/s]

stock

news_id

news

▪▪▪▪

▪▪▪▪

▪▪▪▪

0

酒鬼酒

57463969

酒鬼酒股份有限公司更正公告

1 row × 3 columns

正则表达式的匹配是非常快的,尤其是在预先使用re.compile编译了表达式以后。

我们的数据集包括25 万条新闻标题,需要在每条标题中搜索 3600 个可能的股票名称。在大猫的 Intel 十代 i7 移动版 CPU 上,只花费了 17 秒。 ”

解法 2:正则表达式(找到所有匹配)

在解法二中,我们使用re.findall函数,它能够找到标题中出现的所有股票名。比如“平安银行中国人寿公布第三季度财报”这则标题,代码能够识别出“平安银行”和“中国人寿”两个股票。

代码语言:javascript
复制
# 预先编译表达式
pattern = re.compile('|'.join(stock_name_clean))

# results 用来保存最终结果
results = []

for id, title in tqdm(zip(news_id, news_title)):

    # matched_stock 是一个list,它保存了所有匹配到的股票名。如果列表为空,则意味着
    # 标题中不包含任何股票
    matched_stocks = pattern.findall(title)

    # 如果结果不为空,保存结果
    if len(matched_stocks) > 0:

        # 这里使用了list comprehension, 对每个匹配的stock都新建一个tuple
        out = [(s, id, title) for s in matched_stocks]

        results.extend(out)

# 尝试打印结果的前三行
# 这里大猫使用了datatable包。如果读者使用pandas,那么就注销此条语句,并执行下一条
dt.Frame(results, names=['stock', 'news_id', 'news'])[:,:,dt.sort(f.news)][f.news_id==57467518,:]

# 如果使用pandas,则执行下面语句:
# pd.DataFrame(results, columns=['stock', 'news_id', 'news'])[:3]
代码语言:javascript
复制
249474it [00:19, 12576.39it/s]

stock

news_id

news

▪▪▪▪

▪▪▪▪

▪▪▪▪

0

赛象科技

57467518

金色阳光新股快车—1月5日申购版(赛象科技、奥普光电、皖新传媒)

1

奥普光电

57467518

金色阳光新股快车—1月5日申购版(赛象科技、奥普光电、皖新传媒)

2

皖新传媒

57467518

金色阳光新股快车—1月5日申购版(赛象科技、奥普光电、皖新传媒)

3 rows × 3 columns

从上面的结果可以看到,对于news_id=57467518这则新闻标题,代码成功识别了它里面包含的三个股票:赛象科技、奥普光电、皖新传媒。

正则表达式的匹配是非常快的,即使我们这次匹配的是“所有”股票而不是“出现的第一个股票”,代码也只多跑了 3 秒。

我们的数据集包括25 万条新闻标题,需要在每条标题中搜索 3600 个可能的股票名称。在大猫的 Intel 十代 i7 移动版 CPU 上,只花费了 20 秒。 ”

希望大家觉得这期推送有用!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大猫的R语言课堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题提出
  • 最终效果
  • 解法 1:正则表达式(只找第一个匹配)
  • 解法 2:正则表达式(找到所有匹配)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档