前言: 趁着北京今兒天氣格外的藍,我覺得我得干點什么,於是乎,卷起袖子,整理一下最近做爬蟲的那些事兒。
目標:爬取北京大學軟件與微電子學院的所有新聞,並將內容及圖片存儲到本地。
設計思路:經過對北京大學軟件與微電子學院的新聞網址http://www.ss.pku.edu.cn/index.php/newscenter/news/內容及網頁格式的分析,我發現了這樣一個規律:在每篇文章中,都會有下一篇文章url的鏈接。所以,我的做法是:給定一個初始(最新的)網頁的url,如http://www.ss.pku.edu.cn/index.php/newscenter/news/2391,然后進行一次請求,爬取到下一篇文章的url,用新的url再繼續請求,遞歸調用,直到遍歷完所有的新聞網頁。值得一提的是,我的亮點之一,是可以通過控制一個變量i,來控制爬取文章的數量。
神奇的旅程即將開啟 ….
步驟1:正所謂“工欲善其事,必先利其器”
1)下載nodejs
2)下載JavaScript編輯器webStorm
如果你是個聰明的家伙,你一定能完成這兩個安裝。如果安裝過程中,不幸遇到各種bug,那么請你自行問度娘,安裝好了再繼續往下看。
步驟2:建立工程
友情提醒:請原諒我對webStorm還不太熟悉,我自己也才剛安裝一天,還處於學習階段,所以在DOS操作吧!cmd進入DOS,感覺還是挺酷的!
1)在DOS下cd 進入到你想要創建項目的路徑。
2)mkdir yzx_homework (創建一個yzx_homework文件夾)
3)cd yzx_homework
4) npm init (初始化工程)
此時需要填寫一些項目信息,你可以根據情況填寫,當然也可以一路回車。
創建完項目后,會生成一個package.json的文件。該文件包含了項目的基本信息。
5)安裝第三方包(后面程序會直接調用包的模塊)
說明:由於http模塊、fs模塊都是內置的包,因此不需要額外添加。
這里安裝cheerio包,和request包。
在dos中,cd進入spider文件夾,然后
npm install cheerio –save
安裝完cheerio包后,繼續安裝request包, npm install request –save
說明:npm(nodejs package manager),nodejs包管理器;
–save的目的是將項目對該包的依賴寫入到package.json文件中。
6)在spider文件夾下
- 創建子文件夾data(用於存放所抓取的新聞文本內容)
- 創建子文件夾image(用於存放所抓取的圖片資源)
- 創建一個yzx_spider.js文件
整個項目的目錄結構如下圖所示:
步驟三:”talk is cheep,show me the code .”
打開yzx_spider.js,並一行一行的敲代碼。
你要是個經常“ctrl+c” + “ctrl+v”的家伙,那我就呵呵了!
var http = require('http'); var fs = require('fs'); var cheerio = require('cheerio'); var request = require('request'); var i = 0; var url = "http://www.ss.pku.edu.cn/index.php/newscenter/news/2391"; //初始url function fetchPage(x) { //封裝了一層函數 startRequest(x); } function startRequest(x) { //采用http模塊向服務器發起一次get請求 http.get(x, function (res) { var html = ''; //用來存儲請求網頁的整個html內容 var titles = []; res.setEncoding('utf-8'); //防止中文亂碼 //監聽data事件,每次取一塊數據 res.on('data', function (chunk) { html += chunk; }); //監聽end事件,如果整個網頁內容的html都獲取完畢,就執行回調函數 res.on('end', function () { var $ = cheerio.load(html); //采用cheerio模塊解析html var time = $('.article-info a:first-child').next().text().trim(); var news_item = { //獲取文章的標題 title: $('div.article-title a').text().trim(), //獲取文章發布的時間 Time: time, //獲取當前文章的url link: "http://www.ss.pku.edu.cn" + $("div.article-title a").attr('href'), //獲取供稿單位 author: $('[title=供稿]').text().trim(), //i是用來判斷獲取了多少篇文章 i: i = i + 1, }; console.log(news_item); //打印新聞信息 var news_title = $('div.article-title a').text().trim(); savedContent($,news_title); //存儲每篇文章的內容及文章標題 savedImg($,news_title); //存儲每篇文章的圖片及圖片標題 //下一篇文章的url var nextLink="http://www.ss.pku.edu.cn" + $("li.next a").attr('href'); str1 = nextLink.split('-'); //去除掉url后面的中文 str = encodeURI(str1[0]); //這是亮點之一,通過控制I,可以控制爬取多少篇文章. if (i <= 500) { fetchPage(str); } }); }).on('error', function (err) { console.log(err); }); } //該函數的作用:在本地存儲所爬取的新聞內容資源 function savedContent($, news_title) { $('.article-content p').each(function (index, item) { var x = $(this).text(); var y = x.substring(0, 2).trim(); if (y == '') { x = x + '\n'; //將新聞文本內容一段一段添加到/data文件夾下,並用新聞的標題來命名文件 fs.appendFile('./data/' + news_title + '.txt', x, 'utf-8', function (err) { if (err) { console.log(err); } }); } }) } //該函數的作用:在本地存儲所爬取到的圖片資源 function savedImg($,news_title) { $('.article-content img').each(function (index, item) { var img_title = $(this).parent().next().text().trim(); //獲取圖片的標題 if(img_title.length>35||img_title==""){ img_title="Null";} var img_filename = img_title + '.jpg'; var img_src = 'http://www.ss.pku.edu.cn' + $(this).attr('src'); //獲取圖片的url //采用request模塊,向服務器發起一次請求,獲取圖片資源 request.head(img_src,function(err,res,body){ if(err){ console.log(err); } }); request(img_src).pipe(fs.createWriteStream('./image/'+news_title + '---' + img_filename)); //通過流的方式,把圖片寫到本地/image目錄下,並用新聞的標題和圖片的標題作為圖片的名稱。 }) } fetchPage(url); //主程序開始運行
恭喜你,你總算熬出頭了!
我依然相信,你是一行一行敲代碼的家伙!
運行程序: 見證奇跡的時刻到了!
運行程序:兩種方法:
1) 右鍵yzx_spider.js,打開方式選擇webStorm (安轉node可以使用node yzx_spider.js)
然后進入webStorm,點擊右上角綠色的三角標志,程序便開始運行。
控制台有內容輸出,證明你成功了!!!
控制台輸出的內容,對應的代碼是console.log(news_item),輸出了新聞的信息。
2)如果你對webStorm還一頭霧水,亦或安裝失敗,你可以選擇在dos下運行。
cd 到你創建工程文件夾yzx_homework下,然后 node yzx_spider.js 程序就跑起來了。
本地存儲的資源
1)文本資源:就沒刻意保存所有文章的標題了,最后以文章的標題命名.txt文件。
2)文章的具體內容:文章內容按段落處理,且段與段之間空一行。
3)圖片資源:
4)圖片命名說明:就沒刻意保存文章圖片的標題了。圖片的命名格式為:文章標題+ “—”+圖片標題。
如下圖所示:圖片的標題為“座談會現場”和“參數隊員合影”。
后記:爬蟲項目,其中關鍵就在於選擇器的設計。cheerio包的選擇器$,和jQuery選擇器規則幾乎是一樣的。