文章摘要是一个简短的段落,其中包含要点,并以文章本身使用的词语来表达。通常,我们仅提取那些我们认为最重要的要素/句子,这些要素/句子通常传达主要思想或必要的支撑点。
摘要不是文章的分析,摘要和分析是不同的东西。摘要在很多情况下很有用,例如,获得一篇篇幅较大的文章的要点,用通俗单词介绍一个复杂的想法,从篇幅较大的文章中获得启发等。
在学术上,提取摘要是一项具有挑战性的任务。值得庆幸的是,机器学习出现了。机器学习的自然语言处理(NLP)模块提供了许多可用于文本摘要的算法。文本摘要有两种主要方法:
创建抽象式摘要:
该技术使用高级的NLP方法来生成摘要,该摘要所使用的单词句子是全新的。这意昧着,摘要是用文章中未使用的词创建的。
创建提取式摘要:
在这种技术中,最重要的单词句子被提取出来一起组建一个摘要。显而易见,摘要中使用的单词句子来自文章本身。
在本文中,我们将使用提取技术从大型新闻文章中提取4-5个重要的重要句子构建新闻简报。我们将使用一些流行和有效的策略来处理大量文本并从中提取4-5个有意义的句子。
我们将使用全局向量(也称为GloVe算法),它是单词的向量表示。用外行的话来说,我们将使用GloVe算法生成句子向量,并选择每页排名中最重要的句子。事不宜迟,让我们深入研究代码。我在此练习中使用了python。
处理新闻RSS摘要
我选择研究TimeOfIndia的RSS频道,该公司是印度最受欢迎的新闻服务之一。在本练习中,我选择了新闻的“world”部分。但是代码比较灵活,可以处理各种新闻服务的多个RSS频道。
让我们阅读RSS频道,并将新闻的链接传递到BeautifulSoup进行HTML解析。请注意,这里我仅采用了一个RSS频道,并逐步进行解析。稍后,我将这些步骤结合在一起以完美处理多个频道。
# import basic required libraries
import pandas as pd
import numpy as np
import os # for web and HTML
import requests
from bs4 import BeautifulSoup# create a dict of various
RSS feed link and their categories. Will iterate them one by one.
# Have mentioned only one feed for demo purposes
timesofindia = {'world':'http://timesofindia.indiatimes.com/rssfeeds/296589292.cms'}
for category, rsslink in timesofindia.items():
print('Processing for category: {0}. \nRSS link: {1}'.format(category,rsslink))
# get the webpage URL and read the html
rssdata = requests.get(rsslink)
#print(rssdata.content)
soup = BeautifulSoup(rssdata.content)
print(soup.prettify())
在BeautifulSoup解析之后,我们应该彻底检查了网页的HTML内容(通过使用如上所述的pretifiy函数),然后找到标签/样式或标签序列以进行导航,进而获取所需的新闻标题,链接和pubDate。在我们的例子中,这些元素在“item" 标签内。因此,让我们提取“item",然后遍历每个“item” 标签并提取每个单独的元索。
# get all news items. It has title, description, link, guid, pubdate for each news items.
# Lets call this items and we will iterate thru it
allitems = soup.find_all('item')# print one news item/healine to check
for item in range(len(allitems)):
print('Processing news-item #:',item)
title = allitems[item].title.text
link = allitems[item].guid.text
pubdate = allitems[item].pubdate.text
print('TITLE:',title)
print('LINK:',link)
print('PUBDATE:',pubdate)
输出:
Total news items found: 20
TITLE: Boris Johnson's pregnant fiancee says she is 'on the mend' from coronavirus
LINK: https://timesofindia.indiatimes.com/world/....
PUBDATE: Sun, 05 Apr 2020 17:15:04 IST
TITLE: US to airlift 22,000 Americans stranded overseas; many in India
LINK: https://timesofindia.indiatimes.com/world/.......
PUBDATE: Sun, 05 Apr 2020 14:08:04 IST
TITLE: Ecuador VP apologizes after virus corpses left on streets
LINK: https://timesofindia.indiatimes.com/world/....
PUBDATE: Sun, 05 Apr 2020 14:01:42 IST
得到的元素(例如标题,链接,发布日期)看起来符合我们的预期。让我们进入下一部分,我们将创建一个简单的函数来从链接中获取新闻文章文本。
提取新闻文章
在本节中,我们将通过分析网页的HTML链接来提取新闻文章文本。从RSS feed收到的链接中,我们将取出网页并使用BeautifulSoup 对其进行解析。
网页HTML应该进行被彻底分析,以能够识别所需新闻文本的标签。我创建了一个简单的函数来从链接中获取新闻文本。我将使用BeautifulSoup来提取特定html标签中可用的新闻文本。
# Function to fetch each news link to get news essay
deffetch_news_text(link):
# read the html webpage and parse it
soup = BeautifulSoup(requests.get(link).content, 'html.parser')
# fetch the news article text box
# these are with element <div class="_3WlLe clearfix">
text_box = soup.find_all('div', attrs={'class':'_3WlLe clearfix'})
# extract text and combine
news_text = str(". ".join(t.text.strip() for t in text_box))
return news_text# using the above function, process text
news_articles = [{'Feed':'timesofindia',
'Category':category,
'Headline':allitems[item].title.text,
'Link':allitems[item].guid.text,
'Pubdate':allitems[item].pubdate.text,
'NewsText': fetch_news_text(allitems[item].guid.text)}
for item in range(len(allitems))]news_articles = pd.DataFrame(news_articles)
news_articles.head(3)
为了进行文本清理,我使用了文本的预处理,这些步骤是删除HTML标记,特殊字符,数字,标点符号,停用词,处理重音字符,扩展收缩,词干和词形等。
在这里,我将这些预处理步骤放到一个函数中,该函数将返回干净且标准化的语料库。
# test normalize cleanup on one article
# clean_sentences = normalize_corpus([news_articles['NewsText'][0]])
clean_sentences = normalize_corpus(news_articles['NewsText'])
产生句子向量
我们将使用GloVe词嵌入来生成句子的向量表示。对于本练习,我使用的是经过预先训练的Wikipedia 2014 + Gigaword 5 GloVe向量(https://nlp.stanford.edu/projects/glove/)
# define dict to hold a word and its vector
word_embeddings = {}# read the word embeddings file ~820MB
f = open('.\\GloVe\\glove.6B\\glove.6B.100d.txt', encoding='utf-8')
for line in f:
values = line.split()
word = values[0]
coefs = np.asarray(values[1:], dtype='float32')
word_embeddings[word] = coefs
f.close()# check the length
len(word_embeddings) # 400000
在这个集合中,我们有40万个单词嵌入进去。这些单词嵌入的大小为822 MB。大小可能会因嵌入tokens而异。嵌入越多,精度越高。让我们使用这些单词嵌入为归一化的句子创建向量。对于一个句子,我们将首先获取每个单词的向量,然后将取所有句子/词向量分数的平均值,最终得出这个句子的合并向量分数。
# create vector for each sentences
# list to hold vector
sentence_vectors = []# create vector for each clean normalized sentence
for i in clean_sentences:
if len(i) != 0:
v = sum([word_embeddings.get(w, np.zeros((100,))) for w in i.split()])/(len(i.split())+0.001)
else:
v = np.zeros((100,))
sentence_vectors.append(v)print('Total vectors created:',len(sentence_vectors))
取前N个句子
向量只是平面上的有方向的线段。使用余弦相似度方法,将发现句子之间的相似度。向量间的余弦角越小则越相似。在文章中,我们可以每隔一个句子计算一个余弦角。在这里,也可以使用其他方法,例如欧几里得距离,它们之间距离越小,向量越相似。
接下来,让我们将这个余弦相似度矩阵转换成一个图形,其中节点代表句子,边界将代表句子之间的相似度得分。在此图上,将应用PageRank算法得出每个句子的排名。
import networkx as nx
# build graph and get pagerank
nx_graph = nx.from_numpy_array(sim_mat)
scores = nx.pagerank(nx_graph)
# print final values of sentences
scores
输出:
{0: 0.0651816121717921,
1: 0.0642861521750098,
2: 0.06399116048715114,
3: 0.06432009432128397,
4: 0.06385988469675835,
5: 0.06400525631019922,
6: 0.06520921510891638,
7: 0.06320537732857809,
8: 0.06298228524215846,
9: 0.06399491863786076,
10: 0.0640726538022174,
11: 0.06349704017361839,
12: 0.06357060319536506,
13: 0.057627597033478764,
14: 0.058463972076477785,
15: 0.05173217723913434}
由于我们在第一篇文章中得到了16个句子,因此我们得到了16个分数,每个句子一个。我们根据上面计算的排名选择前N个句子。
最后步骤和结论
如上所述,最终文本需要经过一些处理才能呈现。这些处理可以是将每个句子的首字母大写,从每篇文章的开头删除位置名称,删除多余的空格/制表符/标点符号,更正换行符等。.
最后,我们可以将所有这些步骤放在一起以创建摘要引擎/脚本。可将该脚本安排为每天早晨在选定的RSS频道上运行,并将新闻摘要发送到你的收件箱。这样,您无需遍历所有文章来了解最新信息。或者,你可以创建一个漂亮的HTML页面/小部件以显示主要出版物的新闻摘要。请注意,在上面,我使用了单个RSS频道,但是在创建管道时,可以指定更多的RSS频道。另外,我使用了一些打印语句来显示中间值,可以将这些中间值删除以获得无缝的体验。
希望您喜欢这篇文章。如果您想对其中的任何方法分享任何建议,请随时在评论中说。读者的反馈/评论始终是作家的灵感。
参考:
文本预处理
deephub翻译组:张森豪