1. 整合神策分析 SDK

在 Python 脚本中整合神策分析 SDK,使用神策分析採集並分析用戶數據。

我們推薦使用 pip 管理 Python 專案並取得神策分析 SDK:

pip install SensorsAnalyticsSDK
PY


如果不使用 pip,也可以從 GitHub 下載 神策分析 SDK 的原始碼。

SDK 相容 Python 2.6+ 和 Python3 3.X,不需第三方函式庫。

2. 初始化神策分析 SDK

2.1. 取得設定資訊

首先從神策分析的主頁中,取得數據接收的 URL 和 Token(Cloud 版)。

如果使用神策分析 Cloud 服務,需取得的設定資訊為:

如果用戶使用單機版私有部署的神策分析,預設的設定資訊為:

  •  數據接收網址: http://{$host_name}:8106/sa?project={$project_name}(注:神策分析 1.7 及之前的版本,單機版私有部署預設埠號為 8006)

如果用戶使用叢集版私有部署的神策分析,預設的設定資訊為:

  • 數據接收網址: http://{$host_name}:8106/sa?project={$project_name}

其中 {$host_name} 可以是叢集中任意一台電腦。

如果私有部署的過程中修改了 Nginx 的預設設定,或透過 CDN 等連接神策分析,則請諮詢相關人員取得設定資訊。

2.2. 在程式中初始化 SDK

在程式中初始化的程式碼中建構神策分析 SDK 的執行個體:

在生產環境使用 ConcurrentLoggingConsumer,並結合 LogAgent 工具完成數據採集

import sensorsanalytics

# 初始化一個 Consumer,用於數據傳送
# ConcurrentLoggingConsumer 是將數據寫在 log 檔中,再利用神策提供的 LogAgent 工具傳送數據
consumer = sensorsanalytics.ConcurrentLoggingConsumer('您的 log 檔路徑')
# 使用 Consumer 來建立 SensorsAnalytics 物件
sa = sensorsanalytics.SensorsAnalytics(consumer)

# 記錄用戶登入事件
distinct_id = 'ABCDEF123456789'
sa.track(distinct_id, 'UserLogin', is_login_id=True)

# 上報所有快取數據,測試時可以呼叫除錯數據,線上環境一般可以不呼叫
sa.flush()

sa.close()
PYTHON


程式退出前,需要使用 close() 方法表示關閉,否則可能遺失部分快取的數據。

至此,我們已經可以正常使用神策分析 SDK 了。需了解更多關於 SDK 的使用方法,可以跳到本文末尾的控制神策分析 SDK 一節。

3. 追蹤事件

第一次接入神策分析時,建議先追蹤 3~5 個關鍵的事件,只需要幾行程式碼,便能體驗神策分析的分析功能。例如:

  • 圖片社交產品,可以追蹤用戶瀏覽圖片和評論事件
  • 電商產品,可以追蹤用戶註冊、瀏覽商品和下訂單等事件

用戶透過 track() 介面記錄事件,對於任何事件,必須包含用戶識別符(Distinct ID)和事件名(event_name)兩個參數。同時,用戶可以在 track() 的第三個參數傳入一個 dict 物件,為事件增加自定義事件屬性。以電商產品為例,可以這樣追蹤一次購物行為:

distinct_id = 'ABCDEF123456'

properties = {
# '$time' 屬性是系統預設屬性,傳入 datetime 對象,表示事件發生的時間,如果不填入該屬性,則預設使用系統當前時間
'$time' : datetime.datetime.now(),
# '$ip' 屬性是系統預設屬性,如果伺服器端中能取得用戶 IP 網址,並填入該屬性,神策分析會自動根據 IP 網址解析用戶的省份、城市資訊
'$ip' : '123.123.123.123',
# 商品 ID
'ProductId' : '123456',
# 商品類別
'ProductCatalog' : 'Laptop Computer',
# 是否加入收藏夾,Boolean 型別的屬性
'IsAddedToFav' : True,
}

# 記錄用戶瀏覽商品事件
sa.track(distinct_id, 'ViewProduct', properties, is_login_id=True)

properties = {
# 用戶 IP 網址
'$ip' : '123.123.123.123',
# 商品 ID 列表,list<str> 型別的屬性
'ProductIdList' : ['123456', '234567', '345678'],
# 訂單價格
'OrderPaid' : 12.10,
}

# 記錄用戶訂單付款事件
sa.track(distinct_id, 'PaidOrder', properties, is_login_id=True)
PYTHON


3.1. 事件屬性

如前文中的範例,追蹤的事件可以設定自定義的事件屬性,例如瀏覽商品事件中,將商品 ID、商品分類等資訊作為事件屬性。在後續的分析工作中,事件屬性可以作為統計過濾條件使用,也可以作為維度進行多維分析。對於事件屬性,神策分析有一些規範:

  • 事件屬性是一個 dict 物件
  • dict 中每個元素描述一個屬性,Key 為屬性名稱,必需是 str 型別
  • dict 中,每個元素的 Value 是屬性的值,支援 str、int、float、list、datetime.datetime 和 datetime.date

對於神策分析中事件屬性的更多規範,請參考 數據格式

3.1.1. 系統預設屬性

如前文中範例,事件屬性中以 '$' 開頭的屬性為系統預設屬性,在自定義事件屬性中填入對應 '$' 開頭的屬性值可以覆蓋這些預設屬性:

  • $ip - 填入該屬性,神策分析會自動根據 IP 網址解析用戶的省份、城市資訊,該屬性值為 str 型別;
  • $time - 填入該屬性,神策分析將事件時間設定為屬性值的時間,該屬性值必須為 datetime.datetime 或 datetime.date 型別。請注意,神策分析預設會過濾忽略 365 天前或 3 天後的數據,如需修改請聯繫我們。

關於其他更多預設屬性,請參考 數據格式中 '預設屬性' 一節。

4. 用戶識別

在伺服器端應用中,神策分析也要求為每個事件設定用戶的 Distinct Id,這有助於神策分析提供更準確的留存率等數據。

對於註冊用戶,推薦使用系統中的用戶 ID 作為 Distinct ID,不建議使用用戶名、Email、手機號碼等可以被修改的資訊。對於未註冊的匿名用戶,伺服器端也需要一個 ID 以標記用戶(此 ID 一般情況是神策前端 SDK 產生的 ID)。

所有的 track 和 profile 系列方法建議明確指定 is_login_id 參數,以便明確告知神策分析用戶 ID 的類型。在該用戶未呼叫 track_signup()(登入/註冊)前,is_login_id 參數的值應該為 False,呼叫 track_signup() 後,is_login_id 參數的值應該為 True。

注:請不要在事件屬性或者用戶屬性中傳遞 $is_login_id 參數

4.1. 用戶註冊/登入

當同一個用戶的 Distinct Id 發生變化時(一般情況為匿名用戶註冊行為),可以透過 track_signup() 將舊的 Distinct ID 和新的 Distinct ID 關聯,以確保用戶分析的準確性。例如:

# 匿名ID 由前端傳過來
anonymous_id = '9771C579-71F0-4650-8EE8-8999FA717761'

register_id = '0012345678'

# 用戶註冊/登入時,將用戶註冊 ID 與 匿名 ID 關聯
sa.track_signup(register_id, anonymous_id)
PYTHON

注意,對同一個用戶,track_signup() 一般情況下建議只呼叫一次(通常在用戶註冊時呼叫),用戶登入前後的行為的關聯建議在業務端實作。在神策分析 1.13 版本之前,多次呼叫track_signup() 時,只有第一次關聯行為是有效的。神策分析 1.13 版本之後提供了多裝置 id 關聯的方法。更詳細的說明請參考 標識用戶,並在必要時聯繫我們的技術支援人員。


5. 設定用戶屬性

為了更準確地提供針對人群的分析服務,神策分析 SDK 可以設定用戶屬性,如年齡、性別等。用戶可以在留存分析、分佈分析等功能中,使用用戶屬性作為過濾條件或以用戶屬性作為維度進行多維分析。

使用 profile_set() 設定用戶屬性:

distinct_id = 'ABCDEF123456789'

properties = {
# 用戶性別屬性(Sex)為男性
'Sex' : 'Male',
# 用戶等級屬性(Level)為 VIP
'UserLevel' : 'Elite VIP',
}

# 設定用戶屬性
sa.profile_set(distinct_id, properties, is_login_id=True)
PYTHON


對於不再需要的用戶屬性,可以透過 profile_unset() 介面將屬性刪除。

用戶屬性中,屬性名稱與屬性值的限制條件與事件屬性相同,詳細說明請參考 數據格式

5.1. 記錄初次設定的屬性

對於只在首次設定時有效的屬性,我們可以使用 profile_set_once() 記錄这些屬性。與 profile_set()介面不同的是,如果被設定的用戶屬性已存在,則這條記錄會被忽略而不會覆蓋已有數據,如果屬性不存在則會自動建立。因此, profile_set_once() 比較適用於為用戶設定首次啟用時間、首次註冊時間等屬性。例如:

distinct_id = 'ABCDEF123456789'

# 設定用戶管道屬性(AdSource)為 "App Store"
sa.profile_set_once(distinct_id, {'AdSource' : 'App Store'})

# 再次設定用戶管道屬性(AdSource),設定無效,屬性 "AdSource" 的值仍為 "App Store"
sa.profile_set_once(distinct_id, {'AdSource' : 'Search Engine'})
PYTHON


5.2. 數值型別的屬性

對於數值型的用戶屬性,可以使用 profile_increment() 對屬性值進行累加。常用於記錄用戶付費次數、付費額度、積分等屬性。例如:

distinct_id = 'ABCDEF123456789'

# 設定用戶遊戲次數屬性(GamePlayed),將次數累加1次
sa.profile_increment(distinct_id, {'GamePlayed' : 1}, is_login_id=True)
PYTHON


5.3. 列表型別的屬性

對於用戶喜愛的電影、用戶評價過的餐廳等屬性,可以記錄列表型屬性。需要注意的是,列表型屬性中的元素必須為 String 型別,且元素的值不會自動去重(1.12 之前的神策系统版本才會自動去重)。關於列表型別限制請見 數據格式  中屬性長度限制。

distinct_id = 'ABCDEF123456789'

properties = {
# 電影列表
'Movies' : ['Sicario', 'Love Letter'],
# 遊戲列表
'Games' : ['Call of Duty', 'Halo'],
}

# 傳入properties,設定用戶喜歡的電影屬性(movies)和喜歡的遊戲屬性(games)
# 設定成功後,"Movies" 屬性值為 ["Sicario", "Love Letter"];"Games" 屬性值為 ["Call of Duty", "Halo"]
sa.profile_append(distinct_id, properties, is_login_id=True)

# 傳入屬性名稱和需要插入屬性的值,設定用戶喜歡的電影屬性(Movies)
# 設定成功後 "Movies" 屬性值為 ["Sicario", "Love Letter", "Dead Poets Society"]
sa.profile_append(distinct_id, {'Movies' : ['Dead Poets Society']}, is_login_id=True)

# 傳入屬性名稱和需要插入屬性的值,設定用戶喜歡的電影屬性(Movies),
# 屬性值 "Love Letter" 與已列表中已有元素重複,操作仍有效,
# 設定成功後, "Movies" 屬性值為 ["Sicario", "Love Letter", "Dead Poets Society", "Love Letter"]
sa.profile_append(distinct_id, {'Movies' : ['Love Letter']}, is_login_id=True)
PYTHON


6. 物品元數據上報

在神策推薦專案中,客戶需要將物品元數據上報,以開展後續推薦業務的開發與維護。神策分析 SDK 提供了設定與刪除物品元數據的方法。

item_id物品 ID )和item_type物品所屬型別)共同組成了一個物品的唯一標識。所有的 item 系列方法都必須同時指定物品 ID物品所屬型別這兩個參數,來完成對物品的操作。

6.1. 設定物品

直接設定一個物品,如果已存在則覆蓋。除物品 ID 與 物品所屬型別外,其他物品屬性需在 $properties 中定義。

物品屬性中,屬性名稱與屬性值的限制條件與事件屬性相同,詳細說明請參考 數據格式

# 例如
item_type = 'apple'
item_id = '12345'
sa.item_set(item_type, item_id, {"price": "3"})
PYTHON


6.2. 刪除一个物品

如果物品不被推薦而需要下線,刪除該物品即可,如不存在則忽略。

除物品 ID 與 物品所屬型別外,不解析其他物品屬性

# 例如
item_type = 'apple'
item_id = '12345'
sa.item_delete(item_type, item_id)
PYTHON


7. 設定神策分析 SDK

Python SDK 主要由以下兩個元件構成:

  • SensorsAnalytics: 用於傳送數據的介面物件,建構函函式需要傳入一個 Consumer 執行個體。
  • Consumer: Consumer 會進行實際的數據傳送

為了讓開發者更靈活的接入數據,神策分析 SDK 實作了以下 Consumer:

7.1. LoggingConsumer

用於將數據輸出到指定目錄並按天切割文件,一般用於在 Python 腳本中處理即時數據,產生 log 檔並使用 LogAgent 等工具匯入。適合用於單程式程式。

import sensorsanalytics

# 初始化 Logging Consumer
consumer = sensorsanalytics.LoggingConsumer('/data/sa/access.log')

# 使用 Consumer 來建立 SensorsAnalytics 物件
sa = sensorsanalytics.SensorsAnalytics(consumer)
PYTHON


可以透過參數設定切分間隔和保留的檔案數,預設是每天0點切割,保留所有文件。具體參數含義參考 Python 標準庫 logging.handlers.TimedRotatingFileHandler 文件

# 按小時切分,保留最近10個檔案
consumer = sensorsanalytics.LoggingConsumer('/data/sa/access.log', backupCount=10, when='H')
PYTHON


請不要使用多程式寫入同一個 log 檔,可能會造成數據遺失或者錯亂。如果需要多程式寫入,請使用 ConcurrentLoggingConsumer。

7.2.  ConcurrentLoggingConsumer(推薦)

用於將數據輸出到指定目錄,並自動按  切割文件,與 LoggingConsumer 不同的是,它支援多程式寫入同一個文件。一般用於 Django、uWSGI 等特殊的多程式場景。

import sensorsanalytics

# 當快取的數據量達到參數值時,批量向文件中寫入數據
SA_BULK_SIZE = 1024

# 初始化 Concurrent Logging Consumer,寫入檔案 '/data/sa/access.log.YYYY-MM-DD' 中,log 緩衝區長度為 1024 條
consumer = sensorsanalytics.ConcurrentLoggingConsumer('/data/sa/access.log', SA_BULK_SIZE)

# 使用 Consumer 來建立 SensorsAnalytics 物件
sa = sensorsanalytics.SensorsAnalytics(consumer)

# ...

# 上報所有快取數據,測試時可以呼叫除錯數據,線上環境一般可以不呼叫
sa.flush()
PYTHON

LogAgent 設定文件中一定要註解掉 real_time_file_name 參數,否則無法正常匯入數據。已使用 LoggingConsumer 的客戶建議按照如下步驟切換到 ConcurrentLoggingConsumer:

第 1 步 停掉 LogAgent,並註解掉 LogAgent 設定中的 real_time_file_name 參數。
第 2 步 將 log 目錄下的 real_time_file_name 的檔案加上當前時間的字尾 ".YYYY-MM-DD"。
第 3 步 後端程式升級切換到 ConcurrentLoggingConsumer。
第 4 步 重新啟動 LogAgent。


7.3. DebugConsumer(測試使用)

用於校驗數據匯入是否正確,關於 除錯模式 的詳細資訊,請進入相關頁面查看。請注意:Debug 模式是為方便開發者除錯而設定的模式,該模式會逐條校驗數據並在校驗失敗時拋出異常,效能遠低於正常模式。線上環境使用 Debug 模式會嚴重影響效能並存在崩潰風險,產品上線前請務必替換掉/關閉 Debug 模式。

import sensorsanalytics

# 神策分析數據接收的 URL
SA_SERVER_URL = 'YOUR_SERVER_URL'
# 傳送數據的超時時間,單位毫秒
SA_REQUEST_TIMEOUT = 100000
# Debug 模式下,是否將數據匯入神策分析
# True - 校驗數據,並將數據匯入到神策分析中
# False - 校驗數據,但不進行數據匯入
SA_DEBUG_WRITE_DATA = True

# 初始化 Debug Consumer
consumer = sensorsanalytics.DebugConsumer(SA_SERVER_URL, SA_DEBUG_WRITE_DATA, SA_REQUEST_TIMEOUT)

# 使用 Consumer 來建立 SensorsAnalytics 物件
sa = sensorsanalytics.SensorsAnalytics(consumer)
PYTHON


7.4. ConsoleConsumer

用於將數據輸出到標準輸出,一般用於在 Python 腳本中處理歷史數據,產生 log 檔並使用 BatchImporter 等工具匯入。

import sensorsanalytics

# 初始化 Console Consumer
consumer = sensorsanalytics.ConsoleConsumer()

# 使用 Consumer 來建立 SensorsAnalytics 物件
sa = sensorsanalytics.SensorsAnalytics(consumer)
PYTHON


7.5. DefaultConsumer

通常用於匯入小規模歷史數據的場景。由於是網路直接傳送數據,如果網路出現異常可能會導致數據重發或遺失,因此不要用在任何線上服務中。普通 Consumer,實作,逐條、同步的傳送數據給接收伺服器。

import sensorsanalytics

# 神策分析數據接收的 URL
SA_SERVER_URL = 'YOUR_SERVER_URL'
# 傳送數據的超時時間,單位毫秒
SA_REQUEST_TIMEOUT = 100000

# 初始化 Default Consumer
consumer = sensorsanalytics.DefaultConsumer(SA_SERVER_URL, SA_REQUEST_TIMEOUT)

# 使用 Consumer 來構造 SensorsAnalytics 物件
sa = sensorsanalytics.SensorsAnalytics(consumer)
PYTHON


7.6. BatchConsumer

通常用於匯入小規模歷史數據,或者離線 / 略過匯入數據的場景。由於是網路直接傳送數據,如果網路出現異常可能會導致數據重發或遺失,因此不要用在任何線上服務中。批量傳送數據的 Consumer,當且僅當數據達到指定的量時,才將數據進行傳送。

import sensorsanalytics

# 神策分析數據接收的 URL
SA_SERVER_URL = 'YOUR_SERVER_URL'
# 傳送數據的超時時間,單位毫秒
SA_REQUEST_TIMEOUT = 100000
# 當快取的數據量達到參數值時,批量傳送數據
SA_BULK_SIZE = 100

# 初始化 Batch Consumer
consumer = sensorsanalytics.BatchConsumer(SA_SERVER_URL, SA_BULK_SIZE, SA_REQUEST_TIMEOUT)

# 使用 Consumer 來建立 SensorsAnalytics 物件
sa = sensorsanalytics.SensorsAnalytics(consumer)

# 程式結束前呼叫 close() ,通知 Consumer 傳送所有快取數據
sa.close()
PYTHON


7.7. AsyncBatchConsumer

通常用於匯入小規模歷史數據。使用獨立的執行緒進行數據傳送,利用網絡異步、批量傳送數據的 Consumer。

import sensorsanalytics

# 神策分析數據接收的 URL
SA_SERVER_URL = 'YOUR_SERVER_URL'

# 初始化 AsyncBatchConsumer
consumer = sensorsanalytics.AsyncBatchConsumer(SA_SERVER_URL)

# 使用 Consumer 來建構 SensorsAnalytics 物件
sa = sensorsanalytics.SensorsAnalytics(consumer)

# 程式結束前呼叫 close() ,通知 Consumer 傳送所有快取數據
sa.close()
PYTHON

7.8. 其它設定

匯入歷史數據:預設情況下,神策會過濾發生時間比較久遠數據(例如 10 天之前,實際取決於伺服器端設定),如果想匯入歷史數據,可以透過開啟 Time Free,不受此限制。

# 使用 Consumer 來建構 SensorsAnalytics 物件時,開啟 Time Free
sa = sensorsanalytics.SensorsAnalytics(consumer,enable_time_free = True)
PYTHON