使用Python构建自定义新闻源

image
  • 来源 | 愿码(ChainDesk.CN)内容编辑
  • 愿码Slogan | 连接每个程序员的故事
  • 网站 | http://chaindesk.cn
  • 愿码愿景 | 打造全学科IT系统免费课程,助力小白用户、初级工程师0成本免费系统学习、低成本进阶,帮助BAT一线资深工程师成长并利用自身优势创造睡后收入。
  • 官方公众号 | 愿码 | 愿码服务号 | 区块链部落
  • 免费加入愿码全思维工程师社群 | 任一公众号回复“愿码”两个字获取入群二维码

本文阅读时长:12min

要创建自定义新闻Feed模型,我们需要可以训练的数据。这些培训数据将被输入模型,以教它区分我们感兴趣的文章和我们不感兴趣的文章。

在本文中,我们将学习构建自定义新闻语料库并分别注释与兴趣相对应的大量文章。

创建受监督的训练数据集


在我们在新闻文章中创建我们的品味模型之前,我们需要培训数据。这些培训数据将被输入我们的模型,以教它区分我们感兴趣的文章和我们不感兴趣的文章。要构建此语料库,我们需要注释大量符合这些兴趣的文章。对于每篇文章,我们将其标记为“y”或“n”。这将表明该文章是否是我们希望在我们的日常摘要中发送给我们的文章。

为简化此过程,我们将使用Pocket应用程序。Pocket是一个应用程序,允许您保存故事以供稍后阅读。您只需安装浏览器扩展,然后在希望保存故事时单击浏览器工具栏中的Pocket图标。该文章将保存到您的个人存储库中。Pocket的一个重要功能就是它的用途,能够使用您选择的标签保存文章。我们将使用此功能将有趣的文章标记为“y”,将非有趣的文章标记为“n”。

安装Pocket Chrome扩展程序

我们在这里使用谷歌浏览器,但其他浏览器应该类似。对于Chrome,请进入Google App Store并查找“扩展”部分:

img

点击蓝色的添加到Chrome按钮。如果您已有帐户,请登录,如果您还没有帐户,请继续注册(免费)。完成后,您应该会在浏览器的右上角看到Pocket图标。它将显示为灰色,但是一旦有想要保存的文章,您可以单击它。保存文章后,它将变为红色,如下图所示。

右上角可以看到灰色图标。

img

单击图标时,它会变为红色,表示文章已保存。

img

开始保存您遇到的所有文章。用“y”标记有趣的标签,用“n”标记非有趣的标签。这将需要一些工作。你的最终结果只会和训练集一样好,所以你需要为数百篇文章做这件事。如果您在保存文章时忘记标记文章,则可以随时访问该网站http://www.get.pocket.com,在其中标记。

使用Pocket API检索故事

既然您已经将文章保存到Pocket,那么下一步就是检索它们。为此,我们将使用Pocket API。您可以通过https:// ge tpocket.com/developer/apps/new注册一个帐户。单击左上角的“ 创建新应用程序 ”并填写详细信息以获取API密钥。确保单击所有权限,以便添加,更改和检索文章。

img

填写完成并提交后,您将收到您的消费者密钥。您可以在“ 我的应用”下的左上角找到此信息。这将看起来像下面的屏幕,但显然有一个真正的键:

img

设置完成后,您就可以继续下一步,即设置授权。它要求您输入您的使用者密钥和重定向URL。重定向网址可以是任何内容。在这里,我使用了我的Twitter帐户:

import requests

auth_params = {'consumer_key': 'MY_CONSUMER_KEY', 'redirect_uri':

'https://www.twitter.com/acombs'}

tkn = requests.post('https://getpocket.com/v3/oauth/request',

data=auth_params)

tkn.content

您将看到以下输出:

img

输出将包含下一步所需的代码。将以下内容放在浏览器栏中:

https://getpocket.com/auth/authorize?request_token=some_long_code&redir ect_uri = https% 3A // www.twitter.com / acombs

如果您将重定向网址更改为您自己的网址,请确保对其进行网址编码。这有很多资源。一种选择是使用Python库urllib,另一种是使用免费的在线源。

此时,您应该看到授权屏幕。继续并批准它,我们可以继续下一步:

usr_params = {'consumer_key':'my_consumer_key', 'code':

'some_long_code'}

usr = requests.post('https://getpocket.com/v3/oauth/authorize',

data=usr_params)

usr.content

我们将在此处使用以下输出代码继续检索故事:

img

首先,我们检索标记为“n”的故事:

no_params = {'consumer_key':'my_consumer_key', 'access_token':

'some_super_long_code',

'tag': 'n'}

no_result = requests.post('https://getpocket.com/v3/get',

data=no_params)

no_result.text

上面的代码生成以下输出:

img

请注意,我们在标记为“n”的所有文章上都有一个长JSON字符串。这里有几个键,但我们实际上只对URL感兴趣。我们将继续创建一个包含以下所有URL的列表:

no_jf = json.loads(no_result.text)

no_jd = no_jf['list']

no_urls=[]

for i in no_jd.values():

no_urls.append(i.get('resolved_url'))

no_urls

上面的代码生成以下输出:

img

此列表包含我们不感兴趣的故事的所有URL。现在,让我们把它放在一个

DataFrame对象并将其标记为:

import pandas

no_uf = pd.DataFrame(no_urls, columns=['urls'])

no_uf = no_uf.assign(wanted = lambda x: 'n')

no_uf

上面的代码生成以下输出:

img

现在,我们都准备好了不想要的故事。让我们对我们感兴趣的故事做同样的事情:

ye_params = {'consumer_key': 'my_consumer_key', 'access_token':

'some_super_long_token',

'tag': 'y'}

yes_result = requests.post('https://getpocket.com/v3/get',

data=yes_params)

yes_jf = json.loads(yes_result.text)

yes_jd = yes_jf['list']

yes_urls=[]

for i in yes_jd.values():

yes_urls.append(i.get('resolved_url'))

yes_uf = pd.DataFrame(yes_urls, columns=['urls'])

yes_uf = yes_uf.assign(wanted = lambda x: 'y')

yes_uf

上面的代码生成以下输出:

img

现在我们的训练数据都有两种类型的故事,让我们将它们组合成一个DataFrame:

df = pd.concat([yes_uf, no_uf])

df.dropna(inplace=1)

df

上面的代码生成以下输出:

img

现在我们在一个框架中设置了所有URL和相应的标签,我们将继续为每篇文章下载HTML。我们将使用另一个名为embed.ly的免费服务。

使用embed.ly API下载故事主体


我们将使用embed.ly来执行此操作,但您还可以使用许多其他服务。

第一步是注册embed.ly API访问。您可以在https://app.embed.ly/signup上执行此操作。这是一个简单的过程。确认注册后,您将收到一个API密钥..您只需在HTTPrequest中使用此密钥即可。我们现在就这样做:

import urllib

def get_html(x):

qurl = urllib.parse.quote(x)

rhtml = requests.get('https://api.embedly.com/1/extract?url=' +

qurl + '&key=some_api_key')

ctnt = json.loads(rhtml.text).get('content')

return ctnt

df.loc[:,'html'] = df['urls'].map(get_html)

df.dropna(inplace=1)

df

上面的代码生成以下输出:

img

有了它,我们有每个故事的HTML。由于内容嵌入在HTML标记中,并且我们希望将纯文本提供给我们的模型,我们将使用解析器去除标记标记:

from bs4 import BeautifulSoup def get_text(x):

soup = BeautifulSoup(x, 'lxml')

text = soup.get_text()

return text

df.loc[:,'text'] = df['html'].map(get_text)

df

上面的代码生成以下输出:

img

有了这个,我们就准备好了训练。我们现在可以继续讨论如何将文本转换为模型可以使用的内容。

设置每日个人简报

为了设置带有新闻故事的个人电子邮件,我们将再次使用IFTTT。构建应用程序以查找廉价机票,我们将使用Maker Channel发送POST请求。

首先,单击IFTTT主页上的Create a Recipe。然后,搜索Maker
频道:

img

选择此项,然后选择接收Web请求:

img

然后,为请求命名。我正在使用news_event:

img

单击“创建触发器”完成。接下来,单击它以设置电子邮件。搜索Gmail并单击如下图标:

img

点击Gmail后,点击发送电子邮件。从这里,您可以自定义您的电子邮件。

img

输入您的电子邮件地址,主题行,最后在电子邮件正文中包含Value1。我们将通过我们的POST请求传递我们的故事标题并链接到此。单击“创建”以完成此操作。

现在,我们已准备好生成将按计划运行的脚本,自动向我们发送感兴趣的文章。我们将为此创建一个单独的脚本,但我们现有代码中需要做的最后一件事是序列化我们的矢量化器和我们的模型:

import pickle pickle.dump(model, open (r'/Users/alexcombs/Downloads/news_model_pickle.p', 'wb')) pickle.dump(vect, open (r'/Users/alexcombs/Downloads/news_vect_pickle.p', 'wb'))

有了这个,我们从模型中保存了所需的一切。在我们的新脚本中,我们将阅读这些内容以生成新的预测。我们将使用相同的调度库来运行我们在第3章“构建应用程序以查找廉价机票”中使用的代码。总而言之,我们有以下脚本:

# get our imports. import pandas as pd

from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.svm import LinearSVC

import schedule import time
import pickle import json import gspread import requests
from bs4 import BeautifulSoup

from oauth2client.client import SignedJwtAssertionCredentials


# create our fetching function def fetch_news():
try:
vect =
pickle.load(open(r'/Users/alexcombs/Downloads/news_vect_pickle.p', 'rb'))
model =
pickle.load(open(r'/Users/alexcombs/Downloads/news_model_pickle.p', 'rb'))

json_key =
json.load(open(r'/Users/alexcombs/Downloads/APIKEY.json'))
scope = ['https://spreadsheets.google.com/feeds']


credentials = SignedJwtAssertionCredentials(json_key['client_email'], json_key['private_key'].encode(), scope)
gc = gspread.authorize(credentials)

ws = gc.open("NewStories")
sh = ws.sheet1
zd = list(zip(sh.col_values(2), sh.col_values(3),
sh.col_values(4)))
zf = pd.DataFrame(zd, columns=['title', 'urls', 'html'])
zf.replace('', pd.np.nan, inplace=True)
zf.dropna(inplace=True)

def get_text(x):
soup = BeautifulSoup(x, 'lxml')
text = soup.get_text()
return text

zf.loc[:, 'text'] = zf['html'].map(get_text)

tv = vect.transform(zf['text'])
res = model.predict(tv)

rf = pd.DataFrame(res, columns=['wanted'])
rez = pd.merge(rf, zf, left_index=True, right_index=True)

news_str = ''
for t, u in zip(rez[rez['wanted'] == 'y']['title'],
rez[rez['wanted'] == 'y']['urls']):
news_str = news_str + t + '\n' + u + '\n'

payload = {"value1": news_str}
r =
requests.post('https://maker.ifttt.com/trigger/news_event/with/key/IFTTT_KE
Y', data=payload)

# cleanup worksheet
lenv = len(sh.col_values(1))
cell_list = sh.range('A1:F' + str(lenv))
for cell in cell_list:
cell.value = ""
sh.update_cells(cell_list)
print(r.text)
except:
print('Failed')

schedule.every(480).minutes.do(fetch_news)


while 1: schedule.run_pending() time.sleep(1)

这个脚本将每隔4小时运行一次,从Google表格下载新闻报道,通过模型运行故事,通过向IFTTT发送POST请求以生成预期感兴趣的故事,生成电子邮件,最后,它将清除电子表格中的故事,以便在下一封电子邮件中只发送新故事。

恭喜!您现在拥有自己的个性化新闻Feed!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 这节课让你熟悉Xcode,它是你编写应用程序的工具。你会熟悉Xcode的项目结构和学习如何浏览和使用之间的...
    李晨忧华阅读 1,973评论 0 2
  • 这是一篇翻译作品,水平有限,希望各位指正。各位同学最好去看原文:Storyboards Tutorial in i...
    Eddy_0阅读 1,038评论 0 0
  • 亲爱的老公医院的电话不到5点就打来了,护士说妈妈又晕了,让我们赶紧到医院。你立马起床去医院安排好我去店...
    五度练字玲阅读 184评论 0 2
  • 今天很晚了来写字,刚画了一副思维导图,具体点是有点不忍直视的图像,谁让我一点绘画的天赋都没有呢,好吧,画...
    李乐婶阅读 277评论 0 1
  • 最近喜欢上了陈奕迅的《让我留在你身边》,以前应该听过。最近是在最强大脑上,那些被淘汰的选手走时放的歌,我觉得...
    花魂Sheenagh阅读 231评论 0 1