跨域(Cross-Origin Resource Sharing)的原理可參考這篇「跨來源資源共用」,因為安全性考量,網站主幾可設定收到 HTTP 請求時,是否允許非主機網域的來源進行存取。例如自架站的圖片若不想被盜連,可以設定不允許其他網域存取。
使用 JS 存取第三方 API 或網站資料時,若對方主機未允許 CORS,那麼前端人員可是一點辦法都沒有,只能求助於後端,利用伺服器端程式來繞過此問題。
但是不太可能每個前端人員都自己架個伺服器,花這麼一大筆費用只為了處理跨域問題。值得慶幸的是,有國外免費服務架設伺服器,幫大家處理跨域存取的問題,本篇就來整理一些可用的選擇。
一、跨域存取範例
首先來看幾個範例,瞭解跨域可取得什麼資料:
1. 取得字典翻譯
這篇「誰說前端爬不了資料?使用 crossorigin.me」的作者,想要在自己的網站,直接顯示某翻譯網站的查詢結果,這篇文章也提供了範例程式碼,讀者可自行嘗試。
2. 查詢股票、天氣
這些都是更為實用的功能,直接撈公開資料庫來顯示在自己網站,例如「使用 Yahoo 隱藏版 API 查詢股市資料」。
3. Alexa 網站排名
「Alexa」提供了全世界網站的排名與統計數據,雖然不一定準確,不過至少也是個參考依據。
官方提供了 API 可存取排名數據,例如這個網址可看到 WFU BLOG 的排名:
大致可看到以下的數據資訊:
但若想要執行 jQuery Ajax 來存取這個頁面,瀏覽器會出現 CORS 的錯誤訊息,告知 wfublog.com 不允許進入 alexa.com 的網域:
接下來會示範如何使用跨域代理伺服器(CORS PROXY)取得 ALEXA 網域的資料。
二、YAHOO 的 YQL
1. 使用教學
Yahoo 的 YQL 算是最佛心的跨域代理服務了,功能超強簡直無法想像,可能是內部工程師有需要而做的工具,卻又免費釋出讓前端工作人員可以輕鬆爬其他網站資料,而且可選擇返為資料格式為 XML 或 JSON。
- 使用概念及操作說明可參考這篇「使用 YQL 跨網域讀取網站內容」。
- 以前的 Console 頁面已取消,現在請直接到官網「YQL 」往下捲,看到「Sample YQL Response」這裡即可使用 Console 工具
- 這篇「使用YQL & Yahoo Weather API 查詢天氣」可瞭解如何實際應用這個服務
2. 範例程式碼
現在可以來實作如何取得 ALEXA 資料,首先使用 YQL 的 console 工具:
- Responses 選 "XML" 可取得的 XML 頁面內容
- YQL Query 內容填入 select * from xml where url="https://data.alexa.com/data?cli=10&dat=snbamz&url=https://www.wfublog.com/"
- (補充:如果呼叫第三方 api 取得 json 資料, YQL Query 內容填入 select * from json where url="xxxxx")
- 如上圖,YQL 已成功取得 XML 頁面的資料
- 為了方便 JS 操作,將 Responses 改為 "JSON",重新取得資料
- 複製 Endpoint 的字串,這裡是 YQL 提供的 API 操作網址
以下為使用 JQUERY 的範例程式碼:
$.getJSON("https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D%22http%3A%2F%2Fdata.alexa.com%2Fdata%3Fcli%3D10%26dat%3Dsnbamz%26url%3Dhttps%3A%2F%2Fwww.wfublog.com%2F%22&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=?", function (data) {
console.log(data);
});
這樣就能輕鬆取得 ALEXA 的 JSON 格式資料囉。
三、CORS-ANYWHERE
1. 使用說明
這是一個簡單、免費的跨域代理伺服器:
API 使用很簡單,用以下格式即可:
https://cors-anywhere.herokuapp.com/第三方網址
2. 範例程式碼
以下為使用 JQUERY 的範例程式碼:
$.get("https://cors-anywhere.herokuapp.com/https://data.alexa.com/data?cli=10&dat=snbamz&url=https://www.wfublog.com/", function (data) {
console.log($(data).find("ALEXA"));
});
- 這個服務無法像 YQL 一樣,把取得的 XML 頁面轉換為 JSON 格式
- 我們取回的是一個 XML 物件,可直接用 jQuery 來解析
- 例如用 find 來找到 <ALEXA> 這個節點。其他節點的資料,可用相同手法來分析及取得
3. 補充
- 這個服務,比較適合串接第三方 API 服務,且回傳格式為 JS 物件、JSON
- 這服務較多人使用,因此熱門時段回傳速度比較慢
四、CORS.IO
1. 使用說明
這也是一個簡單、免費的跨域代理伺服器:
- 官網及說明:https://cors.io/
API 使用很簡單,用以下格式即可:
https://cors.io/?第三方網址
2. 範例程式碼
以下為使用 JQUERY 的範例程式碼:
$.get("https://cors.io/?https://data.alexa.com/data?cli=10&dat=snbamz&url=https://www.wfublog.com/", function (data) {
var xml = $.parseXML(data);
console.log($(xml).find("ALEXA"));
});
- 這個服務無法像 YQL 一樣,把取得的 XML 頁面轉換為 JSON 格式
- 這個服務也不像 CORS-ANYWHERE 返回 XML 物件,而是將 XML 整個頁面轉成字串值
- 所以需要先使用 jQuery 的 parseXML 進行解析
- 再用 find 來找到 <ALEXA> 這個節點。其他節點的資料,可用相同手法來分析及取得
3. 補充
- 這個服務一樣比較適合串接第三方 API 服務
- 從作者文件來看,回傳格式偏好為 JSON 格式
五、其他跨域代理服務
- 可參考這篇「List of free CORS proxy server」,作者整理了多個 CORS PROXY,並註解使用心得
- 那麼當讀者發現某個服務失效時,能有其他的替代方案
- 但不是每個都建議使用,因為 WFU 串接某些第三方 API 時,若網址參數有 2 個或以上的問號 "?" 時,返回結果會造成執行判斷上的錯誤
- 至少本篇介紹的服務,都是測試後執行上沒有問題的
更多 Javascript 相關技巧:
请教下,您熟悉cors-anywhere https的部署么?
回覆刪除是这样的,我在自己的服务器上安装了cors-anywhere,但是现在只能在ip的情况下使用,但是现在我想实现:
刪除https://www.xxx.com 这样的效果。现在只能用http,不能用https,请教下。