---
tags: cofacts
GA: UA-98468513-3
---
Youtube scrapping alternatives
=====
:::info
相關討論
- [20200511 Slack](https://g0v-tw.slack.com/archives/C2PPMRQGP/p1589175218421000)
- [20200513 會議記錄](https://g0v.hackmd.io/@mrorz/BJ2GzyK9L#Youtube-API-audit)
- [20200520 會議記錄](https://g0v.hackmd.io/TfMlpKYhS3-boaLTgiriYg?view#Youtube-API-audit)
:::
:::danger
到期時間:2020/5/29
(Youtube 通知時間為 2020/5/8,並給 15 工作天改善)
:::
## 需求
- **檢索**:能檢索到影片標題或 description 符合 query 的文章
- **存檔**:原始影片下架後,編輯仍然可以知道原本影片的標題與 description
## 目前實作
遭遇 youtube 網址時,使用 youtube API [`yt.videos.list()`](https://github.com/cofacts/url-resolver/blob/master/src/lib/fetchYoutube.js#L18-L21) 抓取該 youtube 影片 title & description
此 youtube title 與 description 會暫時儲存在 `urls` index。
- 若一天後沒有任何 articles 或 replies 引用到此 url,此 `urls` 文件就會被清除。
- 若帶有 youtube URL 的文章被存進資料庫,則該 `urls` document 會永遠保存。
例子:https://docs.google.com/document/d/1hlFszsLV9uUJl17L40o6AGZVtyAEoTcLA76wSz969QI/edit
## 目前用量
rumors-api 平均每 3 ~ 5 秒就會要呼叫一次 youtube API 查 title 與 description。
![](https://s3-ap-northeast-1.amazonaws.com/g0v-hackmd-images/uploads/upload_42fc489f1c9b6faf7f4e1805ed3b9547.png)
COVID-19 期間,我們每天幾乎都會把 Youtube API 的「20K query/day」 quota 用滿:
![](https://s3-ap-northeast-1.amazonaws.com/g0v-hackmd-images/uploads/upload_5c9ce5d7830b5993d1cda0b6a76e9b0a.png)
## 遭遇問題
上週 Cofacts 配合 Youtube API Services Team 的 audit 調查,對方表示 Cofacts 在下面兩點不合格:
1. 沒有在 Privacy 與 ToS 中提及 Youtube ToS - [Policy #: III.A.1,2](https://developers.google.com/youtube/terms/developer-policies#a.-api-client-terms-of-use-and-privacy-policies)
2. 沒有每 30 天就重新更新爬到的 non-authorized 資料 - [Policy #: III.E.4.a-g](https://developers.google.com/youtube/terms/developer-policies#e.-handling-youtube-data-and-content)
第二項會影響 Cofacts 的使用——一但原始謠言影片被下架,30 天內資料庫被強制更新,那個影片的 title 與 description 就會被洗掉。
以 [audit 文件內的舉例](https://docs.google.com/document/d/1hlFszsLV9uUJl17L40o6AGZVtyAEoTcLA76wSz969QI/edit
)為例,謠言本體剛好是個被下架的影片,拿另一個被重新上架的影片去查,還能查到對應的訊息。
Cofacts 之所以製作 URL preview,其中一個目的就是為了保存訊息被回報的當下,連結裡面的內容,以供未來查詢比對。如果要求我們每 30 天要更新,效果會大打折扣,以上面這個 COVID-19 陰謀論的例子來說,甚至會影響到 COVID-19 的防疫。
## Mitigation
### Do nothing
Cofacts 在 Youtube 的 API client 會就此失效。
由於[目前程式](https://github.com/cofacts/url-resolver/blob/05400af9a22c52e178783967322bf6bfd01c01ee/src/resolvers/resolveUrls.js#L19-L20)一偵測到 youtube 就呼叫 youtube API,一但 API client 失效,所有 youtube URL 都會抓不到東西。
:warning: **檢索**與**存檔**兩個需求都無法達到。
### 每 30 天重爬所有 youtube
我們可以每天檢查 `urls` 、`articles.hyperlinks`、`articles.replies` 的 youtube 連結,如果 `fetchedAt` 超過 30 天就重新 fetch 新的。
:heavy_check_mark: 30 天內可以**檢索**與**存檔**
:warning: 一但內容下架 30 天之後,**檢索**與**存檔**兩個需求都無法達到。
:warning: 另外,這也會影響我們已經緊繃的每日 youtube API quota。
### 使用 url-resolver 存檔
不使用 Youtube API,直接用 url-resolver 針對 youtube 網頁存檔。
- 桌面版 youtube 執行 JS 後,HTML 約 2MB
- 可抽取標題、正確的 `topImageUrl`
- 抓不到 description
- 手機版 youtube (`m.youtube.com/watch?v=N-4jF62FpY8&app=m`) 執行 JS 後 HTML 約幾百 KB
- 可抽取標題
- `topImageUrl` 會抓到推薦影片的(錯的 `topImageUrl`)
- 抓不到 description
:heavy_check_mark: 完全沒用到 Youtube API;爬蟲行為則是有被 [Terms of use 規範](https://www.youtube.com/t/terms),只要遵守 robots.txt 應該就沒問題。
:warning: **檢索**與**存檔**兩個需求都達到一半(至少有標題)
### 使用 vector
在 articles & replies 不儲存影片標題與 description,改存 embedding vector
query 時使用類似 https://github.com/lior-k/fast-elasticsearch-vector-scoring 這樣的工具來進行檢索。(註:elasticsearch 7 [有內建 `dense_vector`](https://www.elastic.co/guide/en/elasticsearch/reference/7.7/dense-vector.html) 但是是 x-pack 好像要錢 QQ。第三方 vector plugin 好像可以支援到我們用的版本。)
:heavy_check_mark: 符合**檢索**功能(有待實測)
:warning: 不符合**存檔**需求。
### 嵌入預覽視窗
使用 url-resolver 抓取 youtube 網頁存檔(`html`),另開 API 直接輸出 HTML 本體。這樣就能直接做一個顯示網頁當時狀態的 iframe 視窗,讓編輯看看。
不過,由於 cofacts-url-resolver 不會儲存 CSS,所以存下來的 HTML 檔案,在顯示時,會變成下圖右邊這樣:
![](https://s3-ap-northeast-1.amazonaws.com/g0v-hackmd-images/uploads/upload_8d9cd27c3964d3afe1b0a19749c1b02a.png)
如果需要一個「單檔包含 CSS 與圖片」的存檔機制,可以參考 [SingleFile](https://github.com/gildas-lormeau/SingleFile/tree/master/cli) (AGPL 授權)
:heavy_check_mark: 可能有些許**存檔**功能。可與其他 solution 搭配使用。
:warning: 無 CSS 的**存檔**功能,在 youtube 這種介面複雜的網站,可能讓編輯還是有看沒有懂;除非改用 SingleFile
:warning: 無**檢索**功能
### 使用 oembed 格式
[oembed](https://oembed.com/) 定義了分享給第三方嵌入的共享資訊格式,在不需要解析的情況下,能拿到基本的資訊。
例如: https://www.youtube.com/oembed?url=http%3A//youtube.com/watch%3Fv%3DM3r2XDceM6A&format=json
```
{
"provider_name": "YouTube",
"width": 480,
"title": "Amazing Nintendo Facts",
"thumbnail_width": 480,
"author_url": "https://www.youtube.com/user/ZackScott",
"version": "1.0",
"height": 270,
"author_name": "ZackScott",
"html": "<iframe width=\"480\" height=\"270\" src=\"https://www.youtube.com/embed/M3r2XDceM6A?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>",
"type": "video",
"thumbnail_url": "https://i.ytimg.com/vi/M3r2XDceM6A/hqdefault.jpg",
"thumbnail_height": 360,
"provider_url": "https://www.youtube.com/"
}
```
:heavy_check_mark: 完全沒用到 Youtube API;
:warning: **檢索**與**存檔**兩個需求都達到一半(只有標題跟縮圖)