iT邦幫忙

0

YouTube 拿掉營利欄位之後,怎麼從公開頁面判斷一個頻道有沒有營利

  • 分享至 

  • xImage
  •  

以前想知道某個 YouTube 頻道有沒有開營利,有個很多教學都在教的做法:打開影片頁的原始碼,搜尋 is_monetization_enabled,看它是 true 還是 false。這招在 2023 年 11 月失效了,YouTube 把這個欄位從頁面上拿掉,之後沒有任何公開欄位直接寫出營利狀態。

欄位拿掉之後,從外部只能根據頻道公開露出的東西去推論。我們做 MonetizationKit 的檢測器時,把這套推論拆成五個訊號,每個訊號都會回傳通過、未通過或未知三種狀態,最後再組合成四種結論。這篇把資料從哪裡抓、每個訊號怎麼解析、各自會在哪裡誤判,以及規則本身怎麼讓整份資料集出現偏差,一次寫清楚。

先講結論:這些訊號能支持判斷,但不能確認頻道實際有沒有分潤;要確認,仍要看頻道主自己的 YouTube 工作室。

先把門檻弄清楚,因為訊號都是跟著門檻設計的

YouTube 合作夥伴計畫(YPP)目前有兩個級別,數字以 YouTube 說明中心為準(2026 年 11 月核對):

條件 粉絲贊助級 廣告分潤級
訂閱人數 500 1,000
過去 90 天公開上傳 3 部 不要求
過去 365 天有效公開長影片觀看時數 3,000 小時 4,000 小時
或:過去 90 天有效 Shorts 觀看次數 300 萬次 1,000 萬次

粉絲贊助級可以開頻道會員、超級留言、超級感謝等功能,也能連結商店;廣告分潤級才有廣告收益分成。另外,2027 年 2 月 1 日起,新申請廣告分潤級的頻道要改成 8,000 小時或 2,000 萬次 Shorts 觀看,訂閱人數仍是 1,000,粉絲贊助級不變。

這張表跟後面的判斷直接相關:會員按鈕和商店是 YPP 才有的功能,但從 500 訂閱的級別就能開,所以看到它們只能證明「在計畫裡」,不能證明「有拿廣告分潤」。

資料來源:只讀未登入訪客看得到的頁面

檢測器只抓三種頁面:

  1. 頻道的 About 頁:訂閱數、會員按鈕、商店分頁都在這裡。
  2. 頻道的 Videos 頁:拿最近的上傳清單和每支影片的長度。
  3. 影片觀看頁 /watch?v=...:讀播放器設定裡的廣告位。

這三種頁面的 HTML 都內嵌了一大段 JSON。頻道頁是 ytInitialData,觀看頁是 ytInitialPlayerResponse,前端用它來渲染畫面,我們用它來讀結構化資料,不需要去解析 DOM。

有兩條路我們刻意不走。第一是 /youtubei/ 這組內部 API,YouTube 的 robots.txt 對所有爬蟲都禁止這個路徑,我們的程式在每次請求和每一跳重新導向都會先比對一份抄下來的 robots.txt 禁止清單。第二是 YouTube Data API:我們讀 API 開發者政策的理解是,API 使用者不能再去抓 YouTube 頁面,而會員按鈕、商店、廣告這三個關鍵訊號只有頁面上才有,兩者沒辦法兼得,所以整個檢測流程不用官方 API。API 原本給的訂閱數本來就只到三位有效數字,About 頁上的精度一樣,換掉沒有損失。

請求帶的是可辨識的爬蟲 User-Agent,不登入、不偽裝成瀏覽器。

五個訊號,逐一拆開

S1 / S5:訂閱數

從頻道頁頭讀訂閱數,S1 看是否達到 1,000,S5 看是否達到 500。

可靠性:這是資格條件,不是結果。超過 1,000 訂閱卻沒加入計畫的頻道很多;反過來,早期加入的頻道後來可能掉粉,頁頭的數字就會低於門檻。所以 S1 只檢查目前訂閱數是否達到廣告分潤級的申請門檻,不能確認營利狀態。S5 比較有用的是它的反面:低於 500 且沒有其他正面訊號時,我們判為「可能未營利」,但仍保留頻道加入後才掉粉的可能。

要注意兩種「拿不到」:頁頭讀到了但沒有顯示訂閱數,和頁面根本沒讀到。前者是頁面本身沒給,後者是抓取失敗,兩者都記成未知,但原因碼分開記,後面統計失敗率時才不會混在一起。

S2:會員按鈕(加入)

在頻道頁的 JSON 裡找這幾個字串,任一個出現就算有:

id.sponsor_button
SPONSORSHIP_STAR
FLOW_TYPE_SPONSORSHIPS_PURCHASE
membershipButtonRenderer
sponsorButtonRenderer

可靠性:看到按鈕時是很強的證據,因為頻道會員只開放給 YPP 頻道。看不到時幾乎沒有意義,原因有三個:

  • 很多已營利的頻道就是不開會員,連一些大型頻道也沒開。
  • 頻道會員不是每個國家都有。2026 年 10 月 20 日 YouTube 說明中心列出的可用地區是 100 個。
  • 設為「為兒童打造」的頻道,YouTube 會直接關閉會員和商品功能。

第三點我們一開始沒處理,兒童頻道會被當成「沒有會員」而扣分。後來改成:如果頻道被判定為兒童頻道,S2 沒找到按鈕就記成未知,不記成未通過。

S4:商店分頁或商品架

找 merchandiseShelfRenderer,或頻道分頁裡有沒有 Store 分頁。把商店連結到頻道需要 YPP,所以有的時候證據力和 S2 同級。沒有的時候一樣說明不了什麼,因為大部分頻道本來就沒開店,兒童頻道也一樣被關掉。

S3:近期長影片的廣告位

這是五個訊號裡工程量最大、坑也最多的一個。

取樣方式:從 Videos 頁拿最近的上傳,只留長度超過 4 分鐘的影片,取前 3 支,平行去抓觀看頁。片中廣告的資格線是 8 分鐘,這裡的 4 分鐘只是用來篩掉短片,讓樣本比較像「長影片」。還沒開播的首播沒有長度,自然會被濾掉。

解析時看 ytInitialPlayerResponse 底下三個欄位:

  • adPlacements、playerAds:實際下發的廣告位,S3 只認這兩個。
  • adSlots:只代表「有投放機會」,不保證真的會播廣告。只有它、沒有前兩者的情況,我們另外標記成弱訊號,不算進 S3。

順便可以從 adPlacements 裡讀出廣告種類(AD_PLACEMENT_KIND_START 是片頭、MILLISECONDS 是片中、END 是片尾)和片中廣告的時間點 adTimeOffsetStartMilliseconds。

簡化後的解析邏輯大概是這樣:

const player = extractAssignedJson(html, "ytInitialPlayerResponse");
const placements = (player.adPlacements ?? []) as unknown[];
const playerAds = (player.playerAds ?? []) as unknown[];
const slots = (player.adSlots ?? []) as unknown[];

const hasAds = placements.length > 0 || playerAds.length > 0;
const slotsOnly = !hasAds && slots.length > 0; // 弱訊號,不進 S3
const status = player.playabilityStatus?.status; // 只有 "OK" 才算有效樣本

可靠性:廣告不等於分潤。依 YouTube 的服務條款,平台可以在任何內容上投放廣告,美國從 2020 年 11 月、其他地區從 2021 年 6 月開始,沒加入 YPP 的頻道影片上也可能出現廣告,錢由 YouTube 收走。YouTube 說明中心的常見問題也直接寫了這一點。

不過實際抓下來,情況比「有廣告也不代表什麼」好一些。我們在調整規則前做過一輪實測:沒加入 YPP 的頻道,觀看頁幾乎不會出現 adPlacements,19 個樣本是 0 個;已加入的頻道,單次抓取大約有 6% 會漏掉廣告。也就是說,命中一次很有分量,沒命中一次反而說明不了什麼。這個不對稱直接決定了下面的判定方式。

我們沒有用的訊號

超級感謝、超級留言這類功能也是 YPP 的一部分,但目前 MonetizationKit 的檢測器沒有把它們列入訊號,只用上面五個。

抓取時最容易踩的坑:把「讀不到」當成「沒有」

這一節是整個系統裡最重要的設計原則,也是最多 bug 的來源。

機器人驗證頁會偽裝成「沒有廣告」

從資料中心 IP 抓觀看頁,很常拿到 playabilityStatus.status 是 LOGIN_REQUIRED、原因文字是「Sign in to confirm you're not a bot」的頁面。這種頁面沒有任何廣告欄位,如果直接拿 adPlacements 是否為空來判斷,就會得到一個假的「無廣告」。

麻煩的是 LOGIN_REQUIRED 同時也用在年齡限制和私人影片。所以我們只有在原因文字明確符合 /not a bot/i 時才歸類成「被擋」,其他歸類成「內容受限」。HTTP 429 也算被擋。完整的失敗分類是:

分類 意思
blocked 被機器人驗證或限流擋下,換時間、換出口 IP 可能就好
restricted 年齡限制、私人影片等內容本身的限制
unavailable 影片被刪或無法播放
timeout / aborted 單一請求逾時,或整次檢測到了總時限
unreadable 頁面結構認不出來
error 網路錯誤、5xx 等

規則是:只有 playabilityStatus 為 OK 的頁面才算有效樣本,失敗的樣本一律不進分母。3 支影片全部被擋時,結果會另外標示「這次 YouTube 不讓我們的伺服器讀影片頁」,讓使用者知道是我們這邊的問題,晚點再查可能會補上。

頁面改版時,「找不到按鈕」不能算未通過

YouTube 改版後頁面一樣回 200,只是結構變了。這時找不到會員按鈕,只代表我們的解析器讀不懂,不代表頻道沒有。所以頻道頁必須先找到結構錨點(channelMetadataRenderer、pageHeaderViewModel,我們在幾個大小、類型不同的頻道上核對過,每個頻道頁都有),找不到錨點時 S2、S4 都記成未知並發出警報。

訂閱按鈕在概念上更接近會員按鈕,本來是更好的錨點,但未登入的回應裡沒有它,只能放棄。

兒童頻道的判定不能靠介面文字

要知道頻道是不是「為兒童打造」,我們用的是觀看頁播放器設定裡的迷你播放器模式:playabilityStatus.miniplayer.miniplayerRenderer.playbackMode 為 PLAYBACK_MODE_PAUSED_ONLY 時,代表這支影片的迷你播放器被關掉了。實測幾個兒童頻道都是 PAUSED_ONLY,一般頻道是 ALLOW。這個值不會隨介面語言改變,比抓顯示文字穩定。只有取樣到的影片全部是兒童影片,才把整個頻道當成兒童頻道。

限流會讓某些國家的「無法判定」虛高

這是做成資料集之後才發現的。2026 年 9 月 5 日初期抓約 900 個頻道時,爬蟲被限流,剛好在被限流的那幾個小時抓的國家,「無法判定」的比例就特別高。美國一度是 37.1%,放慢速度重抓之後,同一批樣本降到 14.3%。現在失敗率會長期記錄,限流的時段會在圖上變成一個尖峰,比較容易看出來。

怎麼把五個訊號組成一個結論

每個訊號是三值的:pass、fail、unknown。組合時的核心原則是 unknown 不等於 fail。

S3 先用「命中幾支」判,不用比例

因為上面那個不對稱(未入計畫幾乎不出廣告位、已入計畫偶爾漏抓),S3 的規則是看命中數:

function adSampleOutcome(withAds: number, sampled: number) {
  if (sampled === 0) return "unknown";
  if (withAds >= 2 || (withAds >= 1 && withAds === sampled)) return "pass";
  if (withAds === 0 && sampled >= 3) return "fail"; // 唯一的陰性
  return "unknown"; // 例如 1/3、0/2、1/2
}

舊版規則是「三分之二以上有廣告才算通過,否則不通過」,結果 1/3、0/1 都被當成陰性,進一步推出「可能未營利」。改成現在這樣以後,只有至少 3 支都成功抓到、而且全都沒廣告,才算陰性。

四種結論

  1. 可能已營利(likely monetized):訂閱 1,000 以上,S3 通過,再加上會員按鈕、商店,或訂閱數 10 萬以上,三者之一。
  2. 或許已營利(possibly monetized):會員按鈕、廣告、商店任一個通過,但湊不滿上一條。
  3. 可能未營利(likely not monetized):沒有任何正面訊號且訂閱不到 500;或訂閱 1,000 以上,而會員、廣告、商店三個都成功讀到、而且都是陰性。
  4. 無法判定:頻道頁和廣告樣本都讀不到,或讀到的東西兩邊都說不通。

「10 萬訂閱」這一條是後來加的。原本只有會員按鈕能把頻道推到第一級,結果一些家喻戶曉、取樣影片每支都有廣告的大頻道,因為沒開會員就卡在第二級。YouTube 確實能在非合作夥伴頻道投廣告。我們仍把「10 萬訂閱且 S3 通過」列為升到第一級的另一項條件,這是我們選的判定門檻,不能據此確認頻道已加入 YPP。小頻道只有廣告時仍然停在第二級,因為對它們來說,廣告證明不了分潤。

另外注意第 3 條的寫法:只有「讀到了、而且是陰性」才算數。訂閱數讀不到、或 S3 被機器人驗證擋掉,都不算陰性。最後仍要看其他訊號:例如 S3 被擋但有會員按鈕時,會判為「或許已營利」;訂閱不到 500 且沒有正面訊號時,仍可能判為「可能未營利」。

規則本身也會製造偏差

我們把這套檢測跑在 2026 年 9 月的各國熱門頻道上,總共 3,192 個頻道,最後發布了檢測數至少 30 個的 50 個國家,共 3,080 個頻道。做各國排名時,踩到一個很典型的坑。

9 月的規則裡,「可能已營利」一定要有會員按鈕。而頻道會員只在部分地區開放。結果排名最後 8 名,剛好就是 50 國裡不在會員開放清單上的那 8 個國家:俄羅斯、斯里蘭卡、伊拉克、亞塞拜然、巴基斯坦、孟加拉、坦尚尼亞、哈薩克。

把國家分成兩組來看,有會員的 42 國,合併後「可能已營利」比例是 29.6%;沒會員的 8 國是 2.9%。光是「這個國家有沒有開會員」這一個是非題,就解釋了 50 國之間這個比例差異的 57%。這說明會員功能的地區限制會影響判定,但不能據此斷言那些國家的創作者比較少營利。這 8 國檢查的 480 個頻道裡,仍有 14 個被判為第一級。按舊規則,這代表它們都檢出了會員按鈕;為什麼這些頻道能提供會員功能,我們還沒查清楚。

規則改成會員、商店、10 萬訂閱三選一之後,10 月的表格把既有的檢測全部按新規則重算,同時也加入了 9 月之後使用者新查的頻道,所以不是每一列都是原樣本。伊拉克的「可能已營利」從 60 個頻道中的 2 個變成 40 個,坦尚尼亞從 60 個中的 0 個變成 35 個。在 10 月完整的 51 國表格裡,這 8 國排名介於第 6 到第 48 名,不再擠在最後。

從這件事得到的教訓是:一個訊號缺席,只有在它「本來可能出現」的地方才算證據。這次我們增加了商店和 10 萬訂閱兩條升到「可能已營利」的路,減少對會員按鈕的依賴,但目前的規則還沒有按各國的功能開放情況處理訊號缺席。會員、商店、甚至 YPP 本身都不是每個國家都有,跨國比較時仍要把這個限制算進去。

局限

把這些寫出來,是因為做這類工具最容易犯的錯,就是把推論包裝成事實。

  • 只看得到未登入訪客看到的東西。沒有收益數字、沒有工作室資料,YouTube 也沒有確認過任何一個結論。
  • 我們不發布準確率。沒有一份「已知營利狀態」的頻道清單可以拿來驗證,給出一個數字反而是誤導。
  • 在 9 月那份資料集裡,大約每 5 個頻道就有 1 個無法判定,而且分布在各國並不平均,比較兩個國家時要特別注意。
  • 資料集用的是熱門榜頻道,50 國中有 49 國的頻道訂閱數中位數超過 10 萬。某國比例低,只代表我們檢查的那批大頻道露出的訊號比較少,不能推到整個國家的創作者。
  • YouTube 的頁面結構隨時會改。上面所有欄位名稱都是 2026 年 10 月前後核對的,改版後要重新確認,這也是為什麼結構錨點檢查不能省。

每個國家的數字、取樣範圍、9 月和 10 月兩套規則的差異,以及可以自己重跑的程式和套件版本,都整理在資料集背後的方法說明裡,資料以 CC BY 4.0 授權公開。

我在做 MonetizationKit,這篇寫的就是我們檢測器實際在用的方法。如果你也在做類似的爬蟲,或發現哪個欄位又被 YouTube 改掉了,歡迎留言交流。

—— Super Lede


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言