修正中國大陸看不到 Blogger 部落格圖片的問題(Picasa 空間)

這裡介紹如何使用簡單的 jQuery 程式,自動修正中國大陸地區無法看到 Picasa 圖片的問題。

Image Credit: Chris UK

中國大陸因為防火長城(Great Firewall)的限制,導致許多網站在大陸都無法被瀏覽,其中也包含很多知名的部落格與社群網站(如 Blogger、facebook、twitter 等),對於中文網站而言,無法讓大陸的網友閱覽其實是很可惜的。

對於 Google 所提供的 Blogger 部落格空間而言,如果想要讓大陸的網友也看得到,可以透過自訂網域名稱的方式來解決,不過使用這樣的方式雖然網站可以正常開啟,由於站上的圖片預設還是放在 Picasa 的空間中,如果不針對圖片做一些處理,理論上在大陸那邊就會看不到所有的圖片。

WFU BLOG 中詳述了許多種讓大陸讀者可以看到 Blogger 圖片的方式,我個人比較喜歡使用 JavaScript 直接動態更改部落格上面的圖片,不過我只想要針對無法正常載入的讀者來使用這樣的措施,如果在非大陸地區本來就可以正常顯示圖片的狀況,就不需要做更動。

以下是在網頁與圖片都載入完成後,使用 jQuery 函式庫,找出沒有載入成功的圖檔,將其替換成沒有被 GFW 防火牆的網址(要測試一個網址是否有被 GFW 擋掉,可以使用 WebSitePulse)。
$(window).load(function() {
  // 檢查圖檔是否有正確載入
  function isLoaded (img) {
    if (!img.complete) { return false; }
    if (typeof img.naturalWidth != "undefined"
        && img.naturalWidth == 0) {
      return false;
    }
    return true;
  }
  $('img').each( function() {
    var img = $(this).get(0);
    if ( !isLoaded(img) ) {
      var imageSrc = img.src;
      if ( imageSrc.match(/^http:\/\/[^/]+\.blogspot\./) ) {
        var rn = Math.floor(Math.random()*4) + 3;
        var host = "http://lh" + rn + ".googleusercontent.com";
        var newImageSrc = imageSrc.replace(
            /^http:\/\/[^/]+\.blogspot\.[^/]+/, host);
        $(this).attr('src', newImageSrc);
      }
    }
  });
});
基本上這段程式碼就是將那些含有 blogspot 的圖片網址,換成 googleusercontent.com,例如:
http://4.bp.blogspot.com/-A1nvDngFywc/U2N7SiU7wqI/AAAAAAAASXg/XbbTOy1h8PY/s1600/great-wall-lock.jpg
就會換成類似
http://lh4.googleusercontent.com/-A1nvDngFywc/U2N7SiU7wqI/AAAAAAAASXg/XbbTOy1h8PY/s1600/great-wall-lock.jpg
這樣的網址。

如果要紀錄實際執行的狀況,可以使用 Google Analytics 所提供的 API,紀錄更換網址後是否有載入成功:
$(window).load(function() {
  // 檢查圖檔是否有正確載入
  function isLoaded (img) {
    if (!img.complete) { return false; }
    if (typeof img.naturalWidth != "undefined"
        && img.naturalWidth == 0) {
      return false;
    }
    return true;
  }
  // 配合 Google Analytics 紀錄圖檔修正結果
  function imgLoadLog(category, action, label) {
    console.log(category + "(" + action +  "): " + label);
    ga('send', 'event', category, action, label);
  }
  $('img').each( function() {
    var img = $(this).get(0);
    if ( !isLoaded(img) ) {
      var imageSrc = img.src;
      if ( imageSrc.match(/^http:\/\/[^/]+\.blogspot\./) ) {
        var rn = Math.floor(Math.random()*4) + 3;
        var host = "http://lh" + rn + ".googleusercontent.com";
        var newImageSrc = imageSrc.replace(
            /^http:\/\/[^/]+\.blogspot\.[^/]+/, host);
        var msg = imageSrc + " -> " + newImageSrc;
        $(this)
          .load(function() {
            imgLoadLog('Alternative Image', 'OK', msg);
          })
          .error(function() {
            imgLoadLog('Alternative Image', 'Fail', msg);
          })
          .attr('src', newImageSrc);
      } else {
        imgLoadLog('Image Load', 'Fail', imageSrc);
      }
    }
  });
});
這裡程式的第一行我使用 $(window) 的目的在於讓所有圖片的載入動作都結束後,才去檢查圖片有沒有載入成功,不過這樣會有缺點,如果網頁中有某些元件載入的速度特別慢的話(例如廣告或是社群分享按鈕),那麼圖片的修正動作就會被延後,目前尚未解決這個問題,不過我個人感覺影響不大。

如果要將這段 JavaScript 程式碼放在 Blogger 部落格的範本,除了使用 <script> 標簽之外,還要記得要用 CDATA 包起來,這樣才不會造成 Blogger 解析上的錯誤:
<script type='text/javascript'>/*<![CDATA[*/
  // JavaScript 程式碼放在這裡
/*]]>*/</script>

因為我人在台灣,無從測試這樣的作法是否真的可行,在開發程式的時候我就嘗試模擬圖片網址被阻擋的狀況,使用一個錯誤的圖片網址:
http://errorhost.blogspot.com/-A1nvDngFywc/U2N7SiU7wqI/AAAAAAAASXg/XbbTOy1h8PY/s1600/great-wall-lock.jpg
看看我寫的 JavaScript 程式是否可以正常修正它,下面就是這張圖的實際測試情況,如果你有看到下面這張圖就表示修正的過程沒問題。


如果要看詳細的修正過程,可以打開瀏覽器的開發人員工具來看看 console 的 log。


你會發現瀏覽器會先因為無法載入該圖片而產生錯誤訊息,然後經過我們的 JavaScript 修正之後,就可以正常載入了。這是我唯一想到的測試方式,如果大家有什麼建議,歡迎提出來討論。



2014/07/19
這裡的方法我在今年五月的時候,測試是正常的,不過最近赫然發現這個方式似乎已經失效了,可能是 GFW 把這個漏洞補起來的緣故,所以這裡所提供的方式,目前應該是不能使用了。

不知道是不是這篇文章太顯眼,現在連我自己的網址 www.gtwang.org 都被 GFW 擋掉,看來我已經被列在黑名單裡面了。:(
本站已經搬家了,欲查看最新的文章,請至 G. T. Wang 新網站