crawler_Docker_解決用 JavaScript 框架開發的 Web 站點抓取

[轉載,後續補上實踐case]

有了 Docker,用 JavaScript 框架開發的 Web 站點也能很好地支持網絡爬蟲的內容抓取

【編者的話】Prerender 服務可以爲網絡爬蟲提供預先渲染的動態頁面內容,解決了用 JavaScript 框架構建的 Web 站點不支持爬蟲抓取的問題。本文詳細描述了一種解決方案,尤爲是提供了集成 Prerender 服務的 Docker 容器鏡像。

nomore.jpg

若是你正在使用 AngularJS 構建一個面向大衆消費者的應用,你確定但願用戶能把它分享到社交媒體上。對於特定的應用而言,豐富的社交分享差很少是最重要的營銷渠道。所謂「豐富的社交分享」,是指像下面這樣的分享:
Schermata-2015-03-22-alle-17.58_.36_.png

能夠看到, Facebook, Twitter 等社交站點可以獲取很是豐富的內容,不只限於網頁標題和圖片。爲何能夠作到這一點?由於在網頁 HTML 文檔的  head 部分包含了有特別含義的元數據標記。像 Facebook 以及 Pinterest 和 Google+ 等社交站點能讀取遵循 開放圖協議標準的元數據,例如,
<head>
<meta property="og:title" content="My Page" />
<meta property="og:description" content="A description of my page." />
<meta property="og:image" content="http://www.mysite.com/images/my_lovely_face.jpg" />
<!-- etc. -->
</head>

Twitter 也支持相似的機制,不過它用的元數據屬性前綴是  twitter: ,而不是  og: 。

當用戶在社交站點上分享一個 URL 時,社交站點會啓動一個網絡爬蟲去抓取該頁面的內容。網絡爬蟲首先在網頁源文檔中找出各類元數據標記,而後纔會查看常規 HTML 元素的內容,例如,  &lt;head> 標記和網頁中的圖像等。

用 AngularJS(以及其它 JavaScript 框架)開發的 Web 站點不支持爬蟲的抓取

我已經在  Earlyclaim 站點的網頁中添加了全部必需的遵循開放圖協議標準的元數據標記。可是,當我把 Earlyclaim 站點的一個連接分享到 Facebook 時,顯示的結果倒是很是使人失望的:

Schermata-2015-03-22-alle-13.32_.39_.png


致使如此糟糕的結果的緣由很簡單:抓取網頁時,網絡爬蟲並不會執行網頁中的 JavaScript 代碼。所以,爬蟲抓取到的內容是這樣的:
<head>
<meta property="og:title" content="{{meta.title}} - earlyclaim.com" />
<meta property="og:description" content="{{meta.description}}" />
<meta property="og:image" content="{{meta.image}}" />
<!-- etc. -->
</head>

解決方案

解決方案的基本思想是:應用一種在服務器端執行的用戶代理探測方法,識別出當前請求來自於社交站點的爬蟲;此時,服務器不會像處理瀏覽器請求那樣返回一個 AngularJS 模板文件,而是重定向到一個服務器端生成的頁面,頁面中包含了但願提供的元數據標記以及正確填寫的信息。

通過 Google 搜索,以及與其它創業公司  startypchile 的技術人員的討論,咱們發現了  prerender.io 服務,它可以預先渲染好動態頁面的內容。這爲問題的解決奠基了良好的開端。

Prerender 的開發者提供了不少 中間件, 還把  prerender 引擎開源,由於他們認爲

咱們相信搜索引擎優化(SEO)是一種權利,而非一種特權!
固然,若是你願意,也能夠付費使用他們提供的 Prerender 託管服務。

支撐  Earlyclaim 的基礎設施是以  Docker 爲基礎構建的。爲了集成 Prerender 服務,咱們首先在 Docker Hub 中找出相關的幾個容器鏡像,而後進行試用,結果難以使人感到滿意。

咱們的需求包括:
  • 徹底可定製的環境(經過 Kitematic );
  • 可以使用 Redis 做爲緩存數據庫;
  • 當即可用的 Prerender 容器。

這些也是咱們自行構建容器鏡像的緣由!

dpr-ec1-1000x720.png

爲何公開咱們的解決方案

首先,咱們信仰「協同智能」:

協同智能是多主體、分佈式系統的特徵,其中每一個主體(人或者機器)都有惟一的位置,自主地爲問題解決網絡做貢獻。在生態系統中,有機體的協同自治使得演化成爲可能。在天然生態系統中,每一個有機體的惟一標識來自於自身的基因、環境以及它在生態系統中的行爲和位置。天然生態系統爲設計下一代社交網絡提供原則,使之可以支持協同智能、衆包我的的專長、偏好以及在問題解決過程當中的獨特貢獻。
- 摘自  維基百科
咱們的解決方案是創建在開源的  prerender.io 引擎 的基礎之上:沒有它,就不會有咱們的解決方案。 Prerender 團隊太棒了。

其次,一樣重要的是,在與不少創業公司的開發者交流以後,咱們瞭解到:他們不少人都在使用 AngularJS 或者其它框架構建 Web 應用,也須要解決搜索引擎優化/豐富的社交分享問題。然而,因爲不知道解決方法,或者感受解決起來太耗費時間,或許會影響更爲重要的產品發佈時間,他們暫時擱置這個問題,留待之後解決。還有些開發者甚至沒有意識到有這個問題,當從咱們這裏據說了以後,他們請求咱們把解決方案分享出來。

咱們相信這個方案可以加速整個開發進程,由於它解決了一個廣泛的問題。很高興可以分享這個方案。

實現

若是技術人員想把咱們構建的容器鏡像添加到本身的基礎設施中,請參考 Docker Hub 上的文檔: https://registry.hub.docker.co ... edis/

AngularJS 服務

若是是 AngularJS 應用,首先實現下面的代碼:
'use strict';
!(function (window, document, undefined) {
var getModule = function (angular) {
return angular.module('seo', [])
  .run([
    '$rootScope',
    function ($rootScope) {
      $rootScope.htmlReady = function () {
        $rootScope.$evalAsync(function () { // fire after $digest
          setTimeout(function () { // fire after DOM rendering
            if (typeof window.callPhantom === 'function') {
              window.callPhantom();
            }
          }, 0);
        });
      };
    }
  ]);
};
if (typeof define === 'function' && define.amd) {
define(['angular'], getModule);
} else {
getModule(angular);
}
})(window, document);

而後經過 angular.module('youApp', ['seo'])調用。

結論

若是你使用咱們的容器,以爲還不錯,請必定告知咱們( @Earlyclaim)。

若是你以爲有人會對此感興趣,請轉發給他們(點擊社交分享按鈕)!

任何建議,請發推特並通知  @Earlyclaim :很是期待您的觀點和文字!

任何代碼改進,請經過  GitHub 推送合併請求!

順便說一句,咱們熱愛創業公司,咱們熱愛開發者,咱們熱愛社區!開放生態系統萬歲!

原文: Get your Javascript website perfectly crawled with Docker (翻譯:柳泉波 校對:佚名) ===================================== 譯者介紹 柳泉波,讀書喝茶踢球寫程序,目前在華南師範大學廣東高校計算機網絡與信息系統工程中心工做。
相關文章
相關標籤/搜索