參考鏈接:https://github.com/datawhalechina/fun-rec/blob/master/docs/
一、物料側畫像的構建
1.1 新物料來源
物料是通過每天在新聞網站上爬取獲取的,爬取新聞詳細的內容請參照
[2.2.1.4 Scrapy基礎及新聞爬取實戰](https://github.com/datawhalechina/fun-rec/blob/master/docs/第二章 推薦系統實戰/2.2新聞推薦系統實戰/docs/2.2.1.4 scrapy基礎及新聞爬取實戰.md)。新聞爬取是每天凌晨的時候爬取前一天的新聞,這么做的原因是可以爬到更多的物料,缺點就是物料的時效性會延遲一天,新爬取的物料存儲在MongoDB中。
1.2 物料畫像的更新
主要從以下2方面考慮:
-
1.新物料畫像添加到物料庫中
新物料添加到物料庫發生在新聞爬取之后,先對新物料進行簡單的畫像處理,目前定義的畫像字段如下(處理后的畫像存儲在Mongodb):
image.png
具體的邏輯就是遍歷今天爬取的所有文章,然后通過文章的title來判斷這篇文章是否已經在物料庫中(新聞網站有可能有些相同的文章會出現在多天)來去重。然后再根據定義的一些字段,給畫像相應的字段初始化,最后就是存入畫像物料池中。
-
2.舊物料畫像,通過用戶的交互記錄進行更新
關于舊物料畫像的更新,需要先了解舊物料哪些字段會被用戶的行為更新。下面是新聞列表展示頁,我們會發現前端會展示新聞的閱讀、喜歡及收藏次數。而用戶的交互(閱讀、點贊和收藏)會改變這些值。
image.png
為了能夠實時的在前端顯示新聞的這些動態行為信息,我們提前將新聞的動態信息存儲到了redis中,線上獲取的時候是直接從redis中獲取新聞的數據,并且如果用戶對新聞產生了交互,那么這些動態信息就會被更新,我們也是直接更新redis中的值,這樣做主要是為了能夠讓前端可以實時的獲取的新聞最新的動態畫像信息。
通過上面的內容我們了解到,新聞的動態畫像的更新是在redis中進行的,而redis又是一個內存數據庫,資源是非常寶貴的,我們不能一直將新聞的信息存儲在里面,而是每天進行一次更新,只更新那些今天可能會被用來展示的新聞(有些新聞可能從發表到現在太久了,由于新聞的時效性就沒有必要再展示了)。所以為了能夠保存新聞歷史的動態信息,系統還需要每天將redis中的動態新聞信息更新到mongodb存儲的新聞畫像庫中,這里的邏輯也是每天會定時觸發,這里的邏輯會放在更新完新物料的畫像之后,當然這里兩個的先后順序并沒有什么影響,只需要注意更新物料動態畫像的時候一定得再redis數據清空之前。
其實這里還有個邏輯需要說明一下,新聞的畫像庫其實是有兩個的,一個被稱為是特征庫FeatureProtrail, 它存儲了物料的所有字段。還有一個是存儲前端展示內容的畫像庫RedisProtrail, 這個畫像庫中的物料是一樣的多,只不過每個物料存儲的內容不一樣,這個特征庫的內容每天都會被更新,作為存儲再redis中的新聞內容的備份內容。所以在完成了新、舊物料畫像的更新之后,我們需要將最新的物料庫中的新聞信息往RedisProtrail物料庫中寫一份,并去掉一些前端展示不需要的字段內容。
更新完的物料如何添加到redis數據庫中。關于新聞內容在redis中的存儲,我們將新聞的信息拆成了兩部分,一部分是新聞不會發生變化的屬性(例如,創建時間、標題、新聞內容等),還有一部分是物料的動態屬性,在redis中存儲的key的標識分別為:static_news_detail:news_id和dynamic_news_detail:news_id 下面是redis中存儲的真實內容
image.png
image.png
這么做的目的是為了線上實時更改物料動態信息的時候更加高效一點。當需要獲取某篇新聞的詳細信息的時候需要查這兩份數據并將數據這兩部分數據拼起來最終才發送給前端展示。
二、用戶側畫像的構建
主要包括以下兩方面:
- 新注冊用戶畫像的更新
- 老用戶畫像的更新
由于系統中將所有注冊過的用戶都放到了一個表里面(新、老用戶),所以每次更新畫像的話只需要遍歷一遍注冊表中的所有用戶。
在具體的畫像構建邏輯之前,得先了解一下用戶畫像中包含哪些字段,下面是直接從mongo中查出來的。
從上面可以看出,主要是用戶的基本信息和用戶歷史信息相關的一些標簽。對于用戶的基本屬性特征這個可以直接從注冊表中獲取,那么對于跟用戶歷史閱讀相關的信息,需要統計用戶歷史的所有閱讀、喜歡和收藏的新聞詳細信息。為了得到跟用戶歷史興趣相關的信息,我們需要對用戶的歷史閱讀、喜歡和收藏這幾個歷史記錄給存起來,其實這些信息都可以從日志信息中獲取得到,但是這里有個工程上的事情得先說明一下,先看下面這個圖,對于每個用戶點進一篇新聞的詳情頁
最底部有個喜歡和收藏,這個前端展示的結果是從后端獲取的數據,那就意味著后端需要維護一個用戶歷史點擊及收藏過的文章列表。
此外前面也提到了我們可以使用用戶歷史閱讀的文章做用戶畫像,為了更好處理和理解,我們也維護了一份用戶歷史閱讀過的所有文章的mysql表(維護表的核心邏輯就是每天跑一邊用戶日志,更新一下用戶歷史閱讀的記錄),那么此時我們其實已經有了用戶的閱讀、點贊和收藏三個用戶行為表了。
三、畫像自動化構建
上面分別對用戶側和物料側的畫像構建進行了介紹,接下來就是要將上面所有的過程都自動化運行,并且設置好定時任務,其實最核心的一點就是一定要在清除redis數據之前,完成用戶和物料畫像的構建,。
大致的執行邏輯就是:
- 先爬取新聞數據,這里需要注意的是,雖然是今天零點爬數據,但是實際上爬的是前一天的新聞;
- 數據爬完之后,離線更新用戶畫像,物料畫像及線上要存儲再redis中的畫像;
- 最后其實是離線推薦的流程,離線將用戶的排序列表存到redis中,線上直接取就行了。
四、總結
本章節很難,需要理清物料和用戶的邏輯關系,還要將它們自動聯系起來,代碼非常多,很容易出現細節問題,所以需要有扎實的基礎和強大的內心來運行代碼。