社會化海量數據採集爬蟲框架搭建

社會化海量數據採集爬蟲框架搭建css

隨着BIG DATA大數據概念逐漸升溫,如何搭建一個可以採集海量數據的架構體系擺在你們眼前。如何可以作到所見即所得的無阻攔式採集、如何快速把不規則頁面結構化並存儲、如何知足愈來愈多的數據採集還要在有限時間內採集。這篇文章結合咱們自身項目經驗談一下。html

咱們來看一下做爲人是怎麼獲取網頁數據的呢?java

一、打開瀏覽器,輸入網址url訪問頁面內容。
二、複製頁面內容的標題、做者、內容。
三、存儲到文本文件或者excel。mysql

從技術角度來講整個過程主要爲 網絡訪問、扣取結構化數據、存儲。咱們看一下用java程序如何來實現這一過程。web

import java.io.IOException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.lang.StringUtils;

public class HttpCrawler {
       public static void main(String[] args) {

            String content = null ;
             try {
                  HttpClient httpClient = new HttpClient();
                   //一、網絡請求
                  GetMethod method = new GetMethod("http://www.baidu.com" );
                   int statusCode = httpClient.executeMethod(method);
                   if (statusCode == HttpStatus. SC_OK) {
                        content = method.getResponseBodyAsString();
                         //結構化扣取
                        String title = StringUtils.substringBetween(content, "<title>" , "</title>" );
                         //存儲
                        System. out .println(title);
                  }

            } catch (HttpException e) {
                  e.printStackTrace();
            } catch (IOException e) {
                  e.printStackTrace();
            } finally {
            }
      }
}

經過這個例子,咱們看到經過httpclient獲取數據,經過字符串操做扣取標題內容,而後經過system.out輸出內容。你們是否是感受作 一個爬蟲也仍是蠻簡單呢。這是一個基本的入門例子,咱們再詳細介紹怎麼一步一步構建一個分佈式的適用於海量數據採集的爬蟲框架。ajax

整個框架應該包含如下部分,資源管理、反監控管理、抓取管理、監控管理。看一下整個框架的架構圖:正則表達式

社會化海量數據抓取組件圖

    • 資源管理指網站分類體系、網站、網站訪問url等基本資源的管理維護;
    • 反監控管理指被訪問網站(特別是社會化媒體)會禁止爬蟲訪問,怎麼讓他們不能監控到咱們的訪問時爬蟲軟件,這就是反監控機制了;算法

一個好的採集框架,無論咱們的目標數據在哪兒,只要用戶可以看到都應該能採集到。所見即所得的無阻攔式採集,不管是否須要登陸的數據都可以順利採集。如今 大部分社交網站都須要登陸,爲了應對登陸的網站要有模擬用戶登陸的爬蟲系統,才能正常獲取數據。不過社會化網站都但願本身造成一個閉環,不肯意把數據放到 站外,這種系統也不會像新聞等內容那麼開放的讓人獲取。這些社會化網站大部分會採起一些限制防止機器人爬蟲系統爬取數據,通常一個帳號爬取不了多久就會被 檢測出來被禁止訪問了。那是否是咱們就不能爬取這些網站的數據呢?確定不是這樣的,只要社會化網站不關閉網頁訪問,正常人可以訪問的數據,咱們也能訪問。 說到底就是模擬人的正常行爲操做,專業一點叫「反監控」。sql

那通常網站會有什麼限制呢?chrome

必定時間內單IP訪問次數,沒有哪一個人會在一段持續時間內過快訪問,除非是隨意的點着玩,持續時間也不會太長。能夠採用大量不規則代理IP來模擬。

必定時間內單帳號訪問次數,這個同上,正常人不會這麼操做。能夠採用大量行爲正常的帳號,行爲正常就是普通人怎麼在社交網站上操做,若是一我的一天24小時都在訪問一個數據接口那就有多是機器人了。

若是能把帳號和IP的訪問策略控制好了,基本能夠解決這個問題了。固然對方網站也會有運維會調整策略,說到底這是一個戰爭,躲在電腦屏幕後的敵我雙方,爬 蟲必需要能感知到對方的反監控策略進行了調整,通知管理員及時處理。將來比較理想應該是經過機器學習算法自動完成策略調整,保證抓取不間斷。

    • 抓取管理指經過url,結合資源、反監控抓取數據並存儲;咱們如今大部分爬蟲系統,不少都須要本身設定正則表 達式,或者使用htmlparser、jsoup等軟件來硬編碼解決結構化抓取的問題。不過你們在作爬蟲也會發現,若是爬取一個網站就去開發一個類,在規 模小的時候還能夠接受,若是須要抓取的網站成千上萬,那咱們不是要開發成百上千的類。爲此咱們開發了一個通用的抓取類,能夠經過參數驅動內部邏輯調度。比 如咱們在參數裏指定抓取新浪微博,抓取機器就會調度新浪微博網頁扣取規則抓取節點數據,調用存儲規則存儲數據,無論什麼類型最後都調用同一個類來處理。對 於咱們用戶只須要設置抓取規則,相應的後續處理就交給抓取平臺了。

整個抓取使用了 xpath、正則表達式、消息中間件、多線程調度框架(參考)。xpath 是一種結構化網頁元素選擇器,支持列表和單節點數據獲取,他的好處能夠支持規整網頁數據抓取。咱們使用的是google插件 XPath Helper,這個玩意能夠支持在網頁點擊元素生成xpath,就省去了本身去查找xpath的功夫,也便於將來作到所點即所得的功能。正則表達式補充xpath抓取不到的數據,還能夠過濾一些特殊字符。消息中間件,起到抓取任務中間轉發的目的,避免抓取和各個需求方耦合。好比各個業務系統均可能抓取數據,只須要向消息中間件發送一個抓取指令,抓取平臺抓完了會返回一條消息給消息中間件,業務系統在從消息中間件收到消息反饋,整個抓取完成。多線程調度框架以前提到過,咱們的抓取平臺不可能在同一時刻只抓一個消息的任務;也不可能無限制抓取,這樣資源會耗盡,致使惡性循環。這就須要使用多線程調度框架來調度多線程任務並行抓取,而且任務的數量,保證資源的消耗正常。

無論怎麼模擬總仍是會有異常的,這就須要有個異常處理模塊,有些網站訪問一段時間須要輸入驗證碼,若是不處理後續永遠返回不了正確數據。咱們須要有機制能 夠處理像驗證碼這類異常,簡單就是有驗證碼了人爲去輸入,高級一些能夠破解驗證碼識別算法實現自動輸入驗證碼的目的。

擴展一下 :所見即所得咱們是否是真的作到?規則配置也是個重複的大任務?重複網頁如何不抓取?

一、有些網站利用js生成網頁內容,直接查看源代碼是一堆js。 可使用mozilla、webkit等能夠解析瀏覽器的工具包解析js、ajax,不過速度會有點慢。
二、網頁裏有一些css隱藏的文字。使用工具包把css隱藏文字去掉。
三、圖片flash信息。 若是是圖片中文字識別,這個比較好處理,可以使用ocr識別文字就行,若是是flash目前只能存儲整個url。
四、一個網頁有多個網頁結構。若是隻有一套抓取規則確定不行的,須要多個規則配合抓取。
五、html不完整,不完整就不能按照正常模式去扣取。這個時候用xpath確定解析不了,咱們能夠先用htmlcleaner清洗網頁後再解析。
六、 若是網站多起來,規則配置這個工做量也會很是大。如何幫助系統快速生成規則呢?首先能夠配置規 則能夠經過可視化配置,好比用戶在看到的網頁想對它抓取數據,只須要拉開插件點擊須要的地方,規則就自動生成好了。另在量比較大的時候可視化仍是不夠的, 能夠先將類型相同的網站歸類,再經過抓取的一些內容聚類,能夠統計學、可視化抓取把內容扣取出幾個版本給用戶去糾正,最後確認的規則就是新網站的規則。這 些算法後續再講。這塊再補充一下(多謝zicjin建議):

背景:若是咱們須要抓取的網站不少,那若是靠可視化配置須要耗費大量的人力,這是個成本。而且這個交給不懂 html的業務去配置準確性值得考量,因此最後仍是須要技術作不少事情。那咱們可否經過技術手段能夠幫助生成規則減小人力成本,或者幫助不懂技術的業務準 確的把數據扣取下來並大量複製。

方案:先對網站分類,好比分爲新聞、論壇、視頻等,這一類網站的網頁結構是相似的。在業務打開須要扣取的尚未錄 入咱們規則庫的網頁時,他先設定這個頁面的分類(固然這個也能夠機器預先判斷,他們來選擇,這一步必需要人判斷下),有了分類後,咱們會經過「統計學、可 視化判斷」識別這一分類的字段規則,可是這個是機器識別的規則,可能不許確,機器識別完後,還須要人在判斷一下。判斷完成後,最後造成規則纔是新網站的規 則

七、對付重複的網頁,若是重複抓取會浪費資源,若是不抓須要一個海量的去重判斷緩存。判斷抓不抓,抓了後存不存,而且這個緩存須要快速讀寫。常見的作法有bloomfilter、類似度聚合、分類海明距離判斷。

  • 監控管理指無論什麼系統均可能出問題,若是對方服務器宕機、網頁改版、更換地址等咱們須要第一時間知道,這時監控系統就起到出現了問題及時發現並通知聯繫人。

目前這樣的框架搭建起來基本能夠解決大量的抓取需求了。經過界面能夠管理資源、反監控規則、網頁扣取規則、消息中間件狀態、數據監控圖表,而且能夠經過後 臺調整資源分配並能動態更新保證抓取不斷電。不過若是一個任務的處理特別大,可能須要抓取24個小時或者幾天。好比咱們要抓取一條微博的轉發,這個轉發是 30w,那若是每頁線性去抓取耗時確定是很是慢了,若是能把這30w拆分不少小任務,那咱們的並行計算能力就會提升不少。不得不提的就是把大型的抓取任務 hadoop化,廢話不說直接上圖:

社會化海量數據抓取組件圖

今天先寫到這裏,後續再介紹下 日均千萬大型採集項目實戰。

 

 

提到如何搭建一個社會化採集系統架構,講架構通常都比較虛,這一篇講一下如何實戰用低成本服務器作到日流水千萬級數據的分佈式採集系統。

有這樣一個採集系統的需求,達成指標: 須要採集30萬關鍵詞的數據 、微博必須在一個小時採集到、覆蓋四大微博(新浪微博、騰訊微博、網易微博、搜狐微博)。爲了節約客戶成本,硬件爲普通服務器:E5200 雙核 2.5G cpu, 4 G DDR3 1333內存,硬盤 500G SATA 7200轉硬盤。數據庫爲mysql。在這樣的條件下咱們可否實現這個系統目標?固然若是有更好的硬件不是這個文章闡述的內容。現經過採集、存儲來講明一下如何實現:

1、採集,目標是在一個小時內把30萬關鍵詞對應的數據從四大微博採集下來,可以使用的機器配置就是上面配置的普通服務器。採集服務器對硬盤沒有太多要求,屬於cpu密集型運算,需耗費一些內存。評估下來硬件資源不是瓶頸,看下獲取數據的接口有什麼問題?

  • 一、經過各大微博的搜索api。就好比新浪微博API針對一個服務器IP的請求次數,普通權限限制是一個小時1w次,最高權限合做受權一個小時 4w次。使用應用時還須要有足夠的用戶,單用戶每一個應用每小時訪問1000次,最高權限4w次須要40個用戶使用你的應用。達到30w關鍵詞,至少須要8 個應用,若是每一個關鍵詞須要訪問3頁,總共須要24個合做權限的應用。實際操做咱們是不可能爲這個項目作到開發24個合做權限的應用,因此這個方式不是很 合適。新浪微博API限制參考連接
  • 二、經過各大微博的最新微博收集數據,微博剛推出的時候,各大微博都有微博廣場,能夠把最新的微博都收集下來,而後經過分詞,若是出現了30萬關 鍵詞中的一個就留下,其餘就丟棄掉。不過如今除了騰訊微博和搜狐微博有微博廣場相似的功能,新浪微博和網易微博已經沒有這項功能了。另按照新浪微博以前公 布的數據,註冊用戶已經超過5億,每小時超過1億條微博,若是全量採集對數據存儲是個大的考驗,也須要大量的系統資源,實際採集了一億條,也許就1000w條有用,浪費了9000w條數據的資源。
  • 三、經過各大微博的網頁搜索,可見便可抓的方式,結合反監控系統模塊模擬人的正常行爲操做,搜索30萬關鍵詞數據,使資源最大化利用。爲了保證在 一個小時採集到,須要採用分佈式多線程模式抓取,併發採集。併發的時候不能從同一個ip或者同一個ip網段出去,保證對方不會監測到咱們的爬蟲。

咱們最後採用了第三種方式,目前運行情況爲經過30w關鍵詞搜索獲得的全部微博加在一塊兒總量1000多w條天天,新浪和騰訊最多,新浪微博略勝一籌。使用了6臺普通PC服務器,就算一臺機器7000元,總共4萬元硬件設備解決採集硬件問題。總體部署圖爲:

milioncrawler1 (1)

2、存儲,採集下來的數據如何處理?首先存儲採集數據是個密集寫的操做,普通硬盤是否可以支持,mysql數據庫軟件可否支持,將來量忽然增長如何應對?再就是評估存儲空間,天天增量這麼多須要耗費大量的存儲資源,如何存放而且易擴展。

    • 一、如何存儲。正常來講咱們上面配置的服務器,mysql使用myisam引擎一張表最多20w,使用 innodb引擎最多400w,若是超過這個數量,查詢更新速度奇慢。這裏咱們採用一個比較取巧的作法,使用mysql的innodb存儲引擎作了一層緩 存庫,這個緩存庫有兩個緩存表,每一個表只存儲少於300w的數據,有一張表多於300w的數據就切換到另外一張表插入直到超過300w再切換回去。切換成功 後,把多於300w數據的表truncate掉,記得必定要沒有數據插入的時候再truncate,防止數據丟失。這裏必定要用truncate,不能使 用delete,由於delete須要查詢,要用到索引讀寫,而且delete還會寫數據庫log耗費磁盤IO,存儲空間也沒有釋放。truncate和 drop是操做數據庫刪除數據比較好的作法。因爲有兩個表做爲數據插入表,使用數據庫表的自增id並不太合適,須要一個高速的惟一自增Id服務器提供生成 分佈式ID。另數據庫徹底能夠關閉寫事務日誌 ,提升性能,由於抓取的數據當時丟失再啓動抓取就能夠了, 這樣數據庫能夠保持在一個比較高性能的狀況完成插入操做。抓取緩存表結果如圖:

milioncrawler2

    • 二、存儲空間。插入後的數據須要保存下來,不能在超過300w後被truncate掉了。咱們須要有個程序在 達到300萬時被truncate掉以前把數據同步走,存放到另一個庫上(咱們叫作結果庫,結果庫也是使用innodb引擎)。不過咱們天天採集的數據 1000多萬,按天遞增,mysql一張表一天就撐爆了,咱們這個表不是寫操做密集型,因此結果庫能夠存儲多點數據,設定上限500w,可是500萬仍是 存不下1000萬數據。咱們須要對mysql最終結果分庫分表。將數據先按照時間分機器分庫,再按照數據源分表,好比201301經過hash計算的數據 存放在一個機器,201302經過hash計算在另外一個機器。到了機器後再按照天或者半天分表,好比表名爲 weibo_2013020101 、weibo_2013020112。weibo_2013020101表示2月1日上午一個表,weibo_2013020112表示2月1日下午一個 表。光這樣分了仍是不夠,1000w/2=500w,經不起壓力擴展。咱們還須要把表再拆分,好比weibo_2013020101 拆成 weibo_2013020101_1(新浪微博)、weibo_2013020101_2(騰訊微博)、weibo_2013020101_3(網易微 博)、weibo_2013020101_4(搜狐微博)。這樣一張表平均就存放 500w/4 = 125w 條數據,遠遠小於500w上限,還能夠應對將來突發的增加。再從存儲空間來算,就算一條微博數據爲1k,一天 1000w*1k=10G,硬盤500G最多存放50天的數據,因此咱們規劃機器的時候能夠掛接多一點硬盤,或者增長機器。結果庫分表如圖:

milioncrawler3

按照這樣的架構,咱們使用開源免費軟件、低成本服務器搭建的千萬級數據採集系統在生產運轉良好。

相關文章
相關標籤/搜索