故事發展
平靜悠閒的日子,依然是錢少事多,此處想象一個表情。忽然有一天,故事就來了,一個做統計的美女老同學說她懶得自己複製貼上,讓我幫她爬蟲獲取一些文章的內容和制定段落的文字,他們做後續的資料統計和分析,這個忙我當然得幫了,雖然沒爬過。。。哈哈,然後下班之後我就花了幾個小時用自己比較熟悉的nodejs做了這個簡單的小Demo(故事會在文末繼續並附上老同學美照!?)。
目標:
爬取該網站(wwwn.cdc.gov/nchs/nhanes…)的右側列表中DocFile下所有的文章的url,然後去爬到每個文章內部的第一段和最後的表格資訊,如下圖:
(2018.08.31補充)
爬蟲方案分析:
開啟要爬去的主頁,右鍵Doc File下面的某一篇文件,選擇“檢查”可在瀏覽器開發者工具(windows 按F12可直接開啟)中,Element下可看到文件的url地址和整個頁面的DOM結構。
採用相同的方法,可以開啟其中一篇文章,在文章要爬去的位置右鍵,檢視到文章的Dom結構,獲取到其中內容。
簡略思路:
定位到文件所在Table---Table下的Doc File---取出Doc File下的文章url---根據url獲取文章內容---選擇文章內我們要爬去的內容所在DOM---格式化處理並儲存在txt中。
採用的node包如下:
var = require('https')
npm init 初始化搭建專案,然後安裝npm install cheerio與request ,建立app.js填寫程式碼。
專案目錄:
直接上原始碼:
var http = require('http');
var https = require('https')
var fs = require('fs');
var cheerio = require('cheerio');
var urlHeader = 'https://wwwn.cdc.gov'
var urlFather = 'https://wwwn.cdc.gov/nchs/nhanes/search/datapage.aspx?Component=Laboratory&CycleBeginYear=2013'
//初始url
let count = 0;
function findUrlList(x,callback){
https.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 urlArr = [];
$('#GridView1 tbody tr').each(function (index, item) {
let url = urlHeader + $(this).children().next().children('a').attr("href")
startRequest(url)
urlArr.push(url)
})
console.log(urlArr.length)
callback()
});
}).on('error', function (err) {
console.log(err);
});
}
function startRequest(x) {
//採用http模組向伺服器發起一次get請求
https.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 news_item = {
//獲取文章的標題
title: $('div #PageHeader h2').text().trim(),
url: '文章地址: '+x,
firstParagraph: '首段:\n'+$('#Component_Description').next().text().trim(),
codeBookAndFrequencies: '表格資訊: \n'+$('#Codebook').children().text().trim()
};
savedContent($,news_item); //儲存每篇文章的內容及文章標題
});
}).on('error', function (err) {
console.error(err);
});
}
//該函式的作用:在本地儲存所爬取的新聞內容資源
function savedContent($, news_item) {
count++;
let x = '['+count+'] ' + '\n';
x += news_item.url;
x = x + '\n';
x += news_item.firstParagraph;
x = x + '\n';
x += news_item.codeBookAndFrequencies;
x = x + '\n';
x += '------------------------------------------------------------ \n';
x = x + '\n';
x = x + '\n';
//將新聞文字內容一段一段新增到/data資料夾下,並用新聞的標題來命名檔案
fs.appendFile('./data/' + news_item.title + '.txt', x, 'utf-8', function (err) {
if (err) {
console.log(err);
}
});
}
// startRequest(url); //主程式開始執行
findUrlList(urlFather,() => {
console.log('work done')
})複製程式碼
命令列 node app.js 跑起來就可看到結果啦!
爬蟲txt結果檢視:
API參考:
故事繼續
對,我花了兩個間斷簡短的晚上幫她做出來了,然後我發現他想要的不是這樣,而是一個更大更多功能的系統,要和他們的R語言系統對接!!!但是又沒有經費,哈哈,那故事就這樣結束了!但是作為一個很有求知慾的程式君,順帶熟練了一下基本的爬蟲,還是很滿足的!謝謝閱讀,希望能給您一些收穫!
美女請收下,你一定不會失望,哈哈哈哈哈?