使用Python構建自定義新聞源

  • 來源 | 願碼(ChainDesk.CN)內容編輯
  • 願碼Slogan | 鏈接每一個程序員的故事
  • 網站 | http://chaindesk.cn
  • 願碼願景 | 打造全學科IT系統免費課程,助力小白用戶、初級工程師0成本免費系統學習、低成本進階,幫助BAT一線資深工程師成長並利用自身優點創造睡後收入。
  • 官方公衆號 | 願碼 | 願碼服務號 | 區塊鏈部落
  • 免費加入願碼全思惟工程師社羣 | 任一公衆號回覆「願碼」兩個字獲取入羣二維碼

本文閱讀時長:12minhtml

要建立自定義新聞Feed模型,咱們須要能夠訓練的數據。這些培訓數據將被輸入模型,以教它區分咱們感興趣的文章和咱們不感興趣的文章。程序員

在本文中,咱們將學習構建自定義新聞語料庫並分別註釋與興趣相對應的大量文章。json

建立受監督的訓練數據集


在咱們在新聞文章中建立咱們的品味模型以前,咱們須要培訓數據。這些培訓數據將被輸入咱們的模型,以教它區分咱們感興趣的文章和咱們不感興趣的文章。要構建此語料庫,咱們須要註釋大量符合這些興趣的文章。對於每篇文章,咱們將其標記爲「y」或「n」。這將代表該文章是不是咱們但願在咱們的平常摘要中發送給咱們的文章。api

爲簡化此過程,咱們將使用Pocket應用程序。Pocket是一個應用程序,容許您保存故事以供稍後閱讀。您只需安裝瀏覽器擴展,而後在但願保存故事時單擊瀏覽器工具欄中的Pocket圖標。該文章將保存到您的我的存儲庫中。Pocket的一個重要功能就是它的用途,可以使用您選擇的標籤保存文章。咱們將使用此功能將有趣的文章標記爲「y」,將非有趣的文章標記爲「n」。瀏覽器

安裝Pocket Chrome擴展程序

咱們在這裏使用谷歌瀏覽器,但其餘瀏覽器應該相似。對於Chrome,請進入Google App Store並查找「擴展」部分:app

img

點擊藍色的添加到Chrome按鈕。若是您已有賬戶,請登陸,若是您尚未賬戶,請繼續註冊(免費)。完成後,您應該會在瀏覽器的右上角看到Pocket圖標。它將顯示爲灰色,可是一旦有想要保存的文章,您能夠單擊它。保存文章後,它將變爲紅色,以下圖所示。框架

右上角能夠看到灰色圖標。工具

img

單擊圖標時,它會變爲紅色,表示文章已保存。post

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/au... 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!

相關文章
相關標籤/搜索