韓前進
?
Web在線爬蟲的設計與實現(xiàn)
韓前進
(石河子大學 信息科學與技術學院,新疆 石河子 832000)
為了方便用戶簡單高效的獲取互聯(lián)網(wǎng)數(shù)據(jù),提出一種結合Web技術與爬蟲技術的在線輕量級網(wǎng)絡爬蟲。該爬蟲可在Web頁面上進行配置,用戶提交配置到遠程服務器,服務器端爬蟲程序進行數(shù)據(jù)抓取分析,最后由Web應用將結果返回到頁面進行預覽,同時支持生成數(shù)據(jù)結果接口URL,方便用戶調用服務器上爬蟲程序爬到的數(shù)據(jù)。
網(wǎng)絡爬蟲;搜索引擎;Web技術
隨著信息社會的飛速發(fā)展,互聯(lián)網(wǎng)已經達到了一個空前的規(guī)模。網(wǎng)絡爬蟲作為分析互聯(lián)網(wǎng)有效數(shù)據(jù)的得力工具,同樣也在不停發(fā)展。
以往用戶想要采集獲得互聯(lián)網(wǎng)數(shù)據(jù),要么尋找開源的爬蟲,要么自己寫爬蟲,再或者花錢請專業(yè)公司進行數(shù)據(jù)采集。無論是選擇尋找開源的爬蟲還是自己寫爬蟲程序,都需要進行安裝軟件,配置環(huán)境,安裝依賴,學習使用等一系列步驟,對有基礎的用戶來說,這沒什么大不了,但對于沒有基礎的用戶來說,這無疑是一道坎。選擇自己寫爬蟲程序時,還需要耗費大量時間與精力去編寫代碼與調試代碼?;ㄥX請專門的公司進行數(shù)據(jù)采集,除了增加開銷之外,還可能面臨數(shù)據(jù)時效性低的問題。
Web在線爬蟲以期方便用戶簡單高效獲得互聯(lián)網(wǎng)數(shù)據(jù)。它結合了Web技術與爬蟲技術。用戶只需要安裝一個瀏覽器,在配置頁提交相關數(shù)據(jù),即可調用服務器上的爬蟲程序。用戶通過Web應用提供的配置面板,將必要配置提交到服務器,服務器爬蟲程序根據(jù)配置進行數(shù)據(jù)請求處理,最后將結果返回。用戶在登錄的情況下可根據(jù)數(shù)據(jù)抓取結果選擇生成數(shù)據(jù)接口URL,用戶在自己的程序中請求數(shù)據(jù)接口URL得到數(shù)據(jù),將獲得的數(shù)據(jù)構造到自己的應用場景中。
本文將對Web在線爬蟲實現(xiàn)的實現(xiàn)原理、抓取策略、工作流程等進行分析介紹。
動態(tài)網(wǎng)站中相似網(wǎng)頁的網(wǎng)頁結構都是有規(guī)律的。以京東為例,京東網(wǎng)站的每個產品詳情頁中,分析頁面結構,可以看到產品名稱的類名為sku- name。那么,如果想獲得該產品的相關數(shù)據(jù),用戶只需給出目標網(wǎng)址,目標網(wǎng)頁中數(shù)據(jù)所在的標簽,使用標簽選擇器與屬性選擇器就可以得到該類名標簽中的數(shù)據(jù)。根據(jù)這個特點,可以設計讓用戶自行觀察網(wǎng)頁結構,提供標簽選擇器與屬性選擇器,指定目標網(wǎng)頁URL即可讓爬蟲抓取數(shù)據(jù)。
Web在線爬蟲主要分為Web應用與爬蟲程序兩大模塊。
Web應用是用戶與爬蟲程序之間“聯(lián)絡人”,負責中轉用戶調用爬蟲的請求與返回爬蟲處理后的數(shù)據(jù)結果。
爬蟲基于Node.js平臺[1],使用Superagent請求初始頁面URL,獲得整個網(wǎng)頁,使用Cheerio根據(jù)用戶配置中的標簽選擇器與屬性選擇器分析頁面,得到目標數(shù)據(jù)。
為了滿足用戶調用爬蟲爬到的數(shù)據(jù)的需求,Web在線爬蟲支持生成數(shù)據(jù)接口,這是一個返回爬蟲爬取數(shù)據(jù)的URL。Web應用負責與數(shù)據(jù)庫交互,數(shù)據(jù)庫保存用戶的爬蟲配置。生成數(shù)據(jù)接口時,將爬蟲配置寫入數(shù)據(jù)庫,請求數(shù)據(jù)接口時,從數(shù)據(jù)庫獲得配置,將配置設置到爬蟲中進行爬取數(shù)據(jù)。為了提高響應速度,可以將爬蟲爬取結果保存到數(shù)據(jù)庫中,設置定時任務,定時調用爬蟲程序爬取數(shù)據(jù),更新數(shù)據(jù)庫。當用戶請求數(shù)據(jù)接口,直接從數(shù)據(jù)庫取出數(shù)據(jù)進行響應。
Web在線爬蟲運行結構如圖1所示。它分為用戶、Web應用、爬蟲程序與互聯(lián)網(wǎng)四大模塊。用戶發(fā)起調用爬蟲請求,Web應用接受請求并調用爬蟲程序,爬蟲向互聯(lián)網(wǎng)發(fā)起請求,處理分析得到的數(shù)據(jù)之后,將結果遞交Web應用,Web應用將結果反饋給用戶。
圖1 Web在線爬蟲運行結構
爬蟲程序獲得目標數(shù)據(jù)的過程如圖2所示。從一個或若干初始網(wǎng)頁的URL開始,獲得初始網(wǎng)頁上的URL,在抓取網(wǎng)頁的過程中,不斷從當前頁面上抽取新的URL放入隊列,直到滿足停止條件。
圖2 爬蟲獲得目標數(shù)據(jù)的過程
爬蟲獲得中間URL過程如圖3所示,用戶需要提供初始頁面到目標頁面的每一級a標簽位置,以使得爬蟲程序順利找到目標頁面。在目標頁面,用戶需要提供標簽選擇器與屬性選擇器以使得爬蟲獲得目標數(shù)據(jù)。
遍歷策略[2]是爬蟲的核心問題。在爬蟲系統(tǒng)中,待抓取URL隊列是很重要的一部分。待抓取URL隊列中的URL以什么樣的順序排列也是一個很重要的問題,因為這涉及到先抓取哪個頁面,后抓取哪個頁面。決定這些URL排列順序的方法,叫做抓取策略。
爬蟲策略主要有以下幾種:
(1)深度優(yōu)先遍歷策略:
深度優(yōu)先遍歷測試是指網(wǎng)絡爬蟲會從起始頁開始,一個鏈接一個鏈接跟蹤下去,處理完這條線路的鏈接之后,在再轉入下一個起始頁,繼續(xù)跟蹤鏈接。
圖3 爬蟲獲取中間URL的過程
深度優(yōu)先策略不一定能適用于所有情況,深度優(yōu)先如果誤入無窮分枝(深度無限),則不可能找到目標節(jié)點
(2)廣度優(yōu)先策略
廣度優(yōu)先策略是按照樹的層次進行搜索,如果此層沒有搜索完成,不會進入下一層搜索。即,首先完成一個層次的搜索,其次在進行下一層次,也稱之為分層處理。
廣度優(yōu)先遍歷策略屬于盲目搜索,它并不考慮結果存在的可能位置,會徹底地搜索整張圖,因而效率較低,但是,如果盡可能的覆蓋較多的網(wǎng)頁,廣度優(yōu)先搜索方法是較好的選擇。
(3)部分的PageRank的策略
對于已經下載的網(wǎng)頁,連同待抓取URL隊列的URL,形成網(wǎng)頁集合,計算每個頁面的PageRank值,計算完之后,將待抓取隊列中的URL按照網(wǎng)頁級別的值的大小排列,并按照順序依次抓取網(wǎng)址頁面。
(4)OPIC(在線頁面重要性計算)策略:
在算法開始前,給所有頁面一個相同的初始現(xiàn)金,當下載了某個頁面P之后,將P的現(xiàn)金分攤給所有從P中分析出的鏈接,并且將P的現(xiàn)金清空。對于待抓取URL隊列中的所有頁面按照現(xiàn)金數(shù)進行排序。
OPIC與PageRank的區(qū)別在于:PageRank的的的每次需要迭代計算,而OPIC策略不需要迭代過程所以計算速度遠遠快與PageRank的的的,適合實時計算使用。
Web在線爬蟲系統(tǒng)采用廣度優(yōu)先搜索算法,用戶在提供的配置面板中配置從初始頁面到目標頁面搜索路徑,有效避免了廣度優(yōu)先搜索的盲目搜索問題。
廣度優(yōu)先搜索是一種簡單直觀且歷史悠久的遍歷方法。Web在線爬蟲通過一個或一組URL為初始頁面,通過用戶指出的每層的URL(用戶給出a標簽選擇器,利用cheerio分析HTML標簽即可獲取URL),逐層向下請求分析搜索,直到得到目標數(shù)據(jù)。
爬蟲的廣度優(yōu)先搜索路徑如圖4所示,程序首先會從初始頁面中分析獲得所有到目標頁面的一級URL,然后依次請求一級URL,得到網(wǎng)頁數(shù)據(jù),進行分析之后,再得到二級URL,再進行請求分析...請求分析到目標頁面停止,此時在目標頁面運用標簽選擇器與屬性選擇器即可獲得目標數(shù)據(jù)。
圖4 爬蟲的廣度優(yōu)先搜索路徑
(1)用戶發(fā)起URL請求,Web應用響應Web在線爬蟲配置面板
(2)用戶提交爬蟲配置,Web應用將配置遞交爬蟲程序
(3)爬蟲程序根據(jù)遞交的配置,進行數(shù)據(jù)請求,處理分析,最后將處理結果遞交Web應用
(4)Web應用將結果返回用戶
(5)數(shù)據(jù)符合用戶需求,用戶發(fā)起生成數(shù)據(jù)接口請求
(6)Web應用判斷用戶是否登錄,如果登錄,數(shù)據(jù)庫保存用戶提交的爬蟲配置,與數(shù)據(jù)處理結果,如果沒有登錄,返回登錄提示。
(7)程序定時請求從數(shù)據(jù)庫獲得爬蟲配置,調用爬蟲程序,獲得結果數(shù)據(jù)后,更新數(shù)據(jù)庫中結果數(shù)據(jù),保持數(shù)據(jù)庫數(shù)據(jù)“新鮮”
(8)用戶調用數(shù)據(jù)接口,Web應用取出數(shù)據(jù)庫數(shù)據(jù)進行響應
Web在線爬蟲后端采用Node.js平臺,原因是Node.js輕量,生態(tài)豐富。前端使用Vue框架進行頁面搭建。
采用Koa.js[3]Web開發(fā)框架。它具有輕量、表現(xiàn)力豐富、健壯的特點。
采用Superagent[4]請求庫。這是一個輕量的、漸進式的Ajax API,是Node.js里一個非常方便的客戶端請求代理模塊,可讀性較好。
采用Cheerio[5]。這是一個Node.js的抓取頁面模塊,是為服務器特別定制的,快速、靈活、實施的jQuery核心實現(xiàn)。適合各種Web爬蟲程序。
采用Async[6]。這是一個流程控制工具包,提供了直接而強大的異步功能?;贘avaScript為Node.js設計,同時也可以直接在瀏覽器中使用。
采用MongoDB[7]。這是一個基于分布式文件存儲的數(shù)據(jù)庫。它支持的數(shù)據(jù)結構非常松散,是類似JSON的BSON格式。這種文檔結構的存儲方式,使用戶能夠更便捷的獲取數(shù)據(jù)。
采用Vue.js[8]前端框架。這是一套用于構建用戶界面的漸進式框架。
(1)使用Koa.js Web開發(fā)框架,搭建Web應用。
(2)編寫Web前端頁面,負責用戶填寫提交爬蟲配置。爬蟲基本配置項有:1)初始頁面URL。2)初始頁面到中間頁面n中每一級的a標簽選擇器。3)目標頁面目標數(shù)據(jù)的標簽選擇器與屬性選擇器。
(3)將Web頁面配置提供的a標簽選擇器壓入隊列。
(4)編寫爬蟲程序。Superagent請求庫請求初始頁面URL,根據(jù)用戶提供的a標簽選擇器,使用Cheerio分析獲得下一級頁面的URL,將所有獲得到的URL壓入隊列,遞歸調用Superagent,直到a標簽選擇器隊列里,所有標簽都分析完。此時,分析到目標頁面,根據(jù)標簽選擇器與屬性選擇器,得到目標數(shù)據(jù)。
(5)將爬蟲得到的數(shù)據(jù)存入數(shù)組,由Web應用返回給用戶。
(6)為了增強爬取效率,使用Async異步請求庫,進行并發(fā)請求。
(7)為了防止被目標服務器發(fā)現(xiàn)爬蟲爬取數(shù)據(jù)。為Superagent設置請求頭,使用HTTP代理池,代理訪問請求。
(8)調用數(shù)據(jù)接口時,Web應用從數(shù)據(jù)庫查找用戶配置,再調用爬蟲抓取數(shù)據(jù),最后再返回結果。當調用數(shù)據(jù)接口頻率過大時,會對服務器造成不小的壓力。因此,將爬蟲爬取的結果存入數(shù)據(jù)庫,設置定時任務,定時調用爬蟲程序,更新數(shù)據(jù)庫中爬蟲爬取的結果。當請求數(shù)據(jù)接口時,直接從數(shù)據(jù)庫中找到數(shù)據(jù),返回結果。
//爬蟲主函數(shù),根據(jù)a標簽選擇器,得到下一級URL
function splider(urls) {
return new Promise((resolve, reject) => {
//async流程控制庫,控制并發(fā)請求數(shù)量為5
async.mapLimit(urls, 5, function(url, callback) {
//superagent請求url
superagent.get(url).end(function(err, res) {
//服務器響應錯誤,或網(wǎng)絡錯誤
if (err) {
reject(err);
}
//保存結果
var allurls = [];
//將服務器響應內容載入Cheerio
var $ = cheerio.load(res. text);
//分析過濾
$('#list a').each(function(idx, element) {
var $element = $(element);
var href = url.resolve (url, $element.attr('href'));
allurls.push(href);
});
//調用回調函數(shù),將局部結果傳遞到回調函數(shù)中保存,回調函數(shù)內部將局部結果拼接。
callback(null, allurls)
}, function(err, result) {
if (err) reject(err);
//函數(shù)執(zhí)行完畢,將結果 返回
resolve(result);
})
})
})
}
//Koa.js處理Web請求
app.use(async function(ctx, next) {
//用戶以get方式,請求/result路徑
if (ctx.request.path === "/result" && ctx.request.method === "GET") {
//請求參數(shù)(內含爬蟲配置參數(shù))
const body = ctx.request.query;
try {
//響應用戶爬蟲的爬取結果
ctx.response.body = await splider (body.targetUrl);
} catch (e) {
//爬蟲響應失敗,返回錯誤提示
ctx.response.body = "Something was wrong " + e;
}
} else {
await next();
}
});
爬取目標:豆瓣電影排行榜中每部電影的詳細信息。
豆瓣電影排行榜如圖5所示。
豆瓣電影的電影詳情頁如圖6所示。
爬蟲配置頁面如圖7所示。配置頁中爬取深度指出初始頁面到目標頁面之間有幾層,目標網(wǎng)址即初始頁面URL,1級選擇器是初始頁面到目標頁面的a標簽選擇器,2級選擇器則為數(shù)據(jù)所在的普通選擇器,輸出結果格式中保存數(shù)據(jù)的屬性選擇器。
圖5 豆瓣電影排行榜(部分)
圖6 豆瓣電影的電影詳情頁
圖7 在線爬蟲配置頁面
請求數(shù)據(jù)接口響應的爬蟲爬取結果如圖8所示。
圖8 數(shù)據(jù)接口響應的數(shù)據(jù)
數(shù)據(jù)接口實例:http://www.domain.com/inter-face?name=tom&cid=123456
鏈接參數(shù)說明:
name參數(shù)指注冊用戶用戶名。只有注冊用戶才能生成數(shù)據(jù)接口。
cid參數(shù)指當前用戶的爬蟲配置參數(shù)id,每個cid對應數(shù)據(jù)庫中一個爬蟲配置。
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(url-Na-me-String);
// 打開和URL之間的連接
URLConnection connection = realUrl.openConnection();
// 設置通用的請求屬性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立實際的連接
connection.connect();
// 獲取所有響應頭字段
Map
// 遍歷所有的響應頭字段
for (String key : map.keySet()) {
System.out.println(key + "--->" + map.get(key));
}
// 定義 BufferedReader輸入流來讀取URL的響應
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("發(fā)送GET請求出現(xiàn)異常!" + e);
e.printStackTrace();
}
// 使用finally塊來關閉輸入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
sendGet(‘http://www.domain.com/interface’,’name=tom&cid=123456’);
function do_get($url, $params) {
$url = "{$url}?".http_build_query($params);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
do_get("http://www.domain.com/interface", array('name' => 'tom','cid'=>'12345'));
const request = require('request');
request('http://www.domain.com/interface?name= tom&cid=123456',function(error,response, body) {
if (!error && response.statusCode == 200) {
console.log(body)
}
})
本文介紹了Web在線網(wǎng)絡爬蟲設計與實現(xiàn),對在線爬蟲原理進行了簡要分析,并重點對爬蟲實現(xiàn)的關鍵技術進行了講解與實現(xiàn)。雖然市面上爬蟲技術的數(shù)據(jù)采集系統(tǒng)有很多,但基本都需要進行安裝軟件、配置環(huán)境等一系列的過程,如果沒有合適的爬蟲程序,則還需要程序員手動編寫代碼實現(xiàn)自己的爬蟲,而這期間,耗費的時間與精力不言而喻。Web在線爬蟲簡化了過程,只需要在Web頁面上進行簡單的配置,就可以利用服務器上的爬蟲程序,獲得爬取的數(shù)據(jù)結果。選擇生成數(shù)據(jù)接口之后,用戶在自己的程序中,利用HTTP請求庫,請求數(shù)據(jù)接口獲得數(shù)據(jù),將數(shù)據(jù)構造到自己的程序即可。這大大方便了用戶獲取互聯(lián)網(wǎng)上的數(shù)據(jù)。
沒有一種爬蟲程序適用所有應用場景。同樣,對于Web在線爬蟲來說也是如此,Web在線爬蟲爬取的數(shù)據(jù),是以HTTP報文的形式在互聯(lián)網(wǎng)上傳輸,當Web應用響應的數(shù)據(jù)量過大,很容易造成響應超時、響應中斷的結果。所以Web在線爬蟲適合爬取傳輸一些數(shù)據(jù)量較小的數(shù)據(jù)。同時因為互聯(lián)網(wǎng)數(shù)以億計的網(wǎng)站中,網(wǎng)頁結構千差萬別,為了滿足爬蟲的通用性,爬蟲并沒有對Ajax動態(tài)響應的內容進行解析與處理,所以對于一些使用Ajax動態(tài)加載的網(wǎng)頁無能為力。但是,這并不意味著Web在線爬蟲沒有實用價值。使用Web在線爬蟲,可以用來監(jiān)控目標網(wǎng)站數(shù)據(jù),比如,我想知道北京到西安的某一個航班在10月的機票價格情況,可以使用Web在線爬蟲爬取航空公司網(wǎng)站,生成數(shù)據(jù)接口之后,用戶每天請求數(shù)據(jù)接口,將得到的數(shù)據(jù)保存匯總即可。同樣,還可以用來監(jiān)控自己在購物網(wǎng)站上喜愛的物品降價沒有,自己追的劇更新沒有等等。
[1] alsotang. 使用superagent與cheerio完成簡單爬蟲[OL]. (2014-10-27)[2018-07-5]. https://github.com/alsotang/node- lessons/tree/master/lesson3.
[2] neituime. 網(wǎng)絡爬蟲基本工作流程和抓取策略[OL]. (2015- 12-08)[2018-07-6]. https://blog.csdn.net/neituime/article/det-ails/50218833.
[3] StrongLoop. Koa-next generation web framework for node.js [OL]. [2018-07-6]. https://koajs.com.
[4] visionmedia.SuperAgent-elegant API for AJAX in Node and browsers[OL]. [2018-07-6]. http://visionmedia.github.io/sup-era-gent/.
[5] cheeriojs. Cheerio[OL](2018-7-7)[2018-7-8]. https://github. com/cheer-iojs/cheerio.
[6] caolan. async [OL].(2018-5-20) [2018-7-10]. https://caolan. github.io/async/.
[7] Dwight, Merriman, Eliot, Horowitz, Kevin, Ryan. MongoDB Documentation [OL]. [2018-7-10]. https://docs.mongodb.com/.
[8] Phan An, defcc, Jinjiang. Vue教程[OL]. [2018-7-10]. https: //cn.vuejs.org/v2/guide/index.html.
[9] 五指少年. java發(fā)送http請求[OL]. (2016-08-31) [2018- 07-10]. https://www.cnblogs.com/xrab/p/5825105.html.
[10] 小云云. PHP實現(xiàn)發(fā)送HTTP請求[OL]. (2018-03-27) [2018- 07-10]. http://www.php.cn/php-weizijiaocheng-390267.html.
Design and Implementation of Web Online Crawler
HAN Qian-jin
(Shihezi University, Shihezi Xinjiang, 832000, China)
In order to facilitate users to obtain Internet data simply and efficiently, an online lightweight web crawler combining Web technology and crawler technology is proposed. The crawler can be configured on the Web page, the user submits the configuration to the remote server, the server crawler program carries out the data capture and analysis, and finally returns the result to the page for preview by the Web application, and supports the generation of the data result interface URL, which is convenient for the user to call the data crawled by the crawler program on the server.
Search engines; Web crawler; Web technology
TP393.092
A
10.3969/j.issn.1003-6970.2018.09.018
韓前進(1996-),男,石河子大學信息科學與技術學院計算機科學與技術專業(yè)學生。
本文著錄格式:韓前進. Web在線爬蟲的設計與實現(xiàn)[J]. 軟件,2018,39(9):86-92