最近個人好友在寫項目的時候常常會抱怨數據的來源,的確對於一個前端來講,數據接口數據資源永遠是Mock。網上看不少大神python,node玩的飛起。但自我感受,並無一套好的流程方案能夠走進咱們開發的流程中。爲了幫助個人好友而且須要數據的你來講,能夠仔細的看看整套流程。由於我也是個前端,因此知道你們須要的是什麼以及處理的方案。那麼就跟着我一塊兒學習下吧!css
學海無涯,我但願你能夠跟着個人思路簡單的實現下,與其臨淵羨魚,不如退而結網。文章中我會詳細講解每一步的操做和細節,nodejs一些經常使用的API,以及koa2簡單的語法,你們也能夠由此文開始你的koa2學習,真的很好用的一個web框架。另外文章中也會講解數據跨域請求的方案和具體實現,最後就是數據的格式化處理和基本請求。三強上場,共唱一出好戲。html
http.request:node http 模塊的request方法能夠做爲httpclient向服務器發起http請求,爬蟲須要向目標連接發起http請求來得到頁面信息前端
建立一個新文件夾,進入以後,咱們初始化生產package.json文件vue
npm init -y
生成的package.json後,安裝koa包,這裏咱們用npm來安裝node
npm initall --save koa
其餘的依賴跟上面同樣的方式安裝,這裏就不展開了,寫在一塊兒python
npm install --save koa-static npm install --save koa2-cors
唱戲以前必定要排練好,要有劇本,每一個人都應該清楚的知道本身的身份和出場時間。那麼每次上臺時都須要排練下,熱下身。這樣才能演繹一出好戲。咱們也同樣,先來一端代碼熱熱身。在咱們的文件夾下新建一個demo01.js吧,而後輸入下面一端代碼jquery
var http = require('http') // Node.js提供了http模塊,用於搭建HTTP服務端和客戶端 var url = 'http://www.runoob.com/nodejs/nodejs-tutorial.html'; //輸入任何網址均可以 http.get(url,function(res){ //發送get請求 var html='' res.on('data',function(data){ html += data //字符串的拼接 }) res.on('end',function(){ console.log(html) }) }).on('error',function(){ console.log('獲取資源出錯!') })
打開終端,執行node demo01.js命令,你就會看到這個網頁全部的html結構,這也是爲咱們的大戲敲響了第一聲鑼鼓。
ios
在上面咱們能夠獲得這個網頁的全部HTML,這就覺得着咱們能夠在這個HTML裏去尋找咱們須要的資源。nodejs爲此提供了一種很是快捷而且方便的cheerio API。前言部分已介紹了它的功能,這裏就直接演示怎麼操做。
引入咱們的cheeriogit
const cheerio = require('cheerio')
引用以後咱們在把它包裝一下,讓他更像jquery,jquery的有點就是對dom操做的很是的簡單程序員
var $ = cheerio.load(html)
接下來就是去咱們的html中尋找咱們須要的資源了,每一個人的需求都是不同的,這裏就以案例爲主,去獲取imooc上的視頻資源。爲了讓咱們的主體(前面熱身提到的)可讀性良好,所以咱們把這部分封裝成一個函數,就收html爲參數.
function filterChapters(html) { var $ = cheerio.load(html) var chapters = $('.course-wrap') //在html裏尋找咱們須要的資源的class var courseData = [] // 建立一個數組,用來保存咱們的資源 chapters.each(function(item) { //遍歷咱們的html文檔 var chapter = $(this) var chapterTitle = chapter.find('h3').text().replace(/\s/g, "") var videos = chapter.find('.video').children('li') //使用childern去獲取下個節點 var chapterData = { chapterTitle: chapterTitle, videos: [] } videos.each(function(item) { //遍歷視頻中的資源,title,id, url var video = $(this).find('.J-media-item') //一樣的方式找到咱們須要的class部分 var videoTitle = video.text().replace(/\n/g, "").replace(/\s/g, ""); var id = video.attr('href').split('video/')[1]; //切割咱們的href的到咱們的id var url = `http://www.imooc.com/video/${id}` // es6字符串模板的方式去經過id拿到咱們的視頻url chapterData.videos.push({ title:videoTitle, id: id, url: url }) }) courseData.push(chapterData) }) return courseData //返回咱們須要的資源 }
採坑記錄:咱們獲得的資源可能有換行符或者空格符之類的,若是不去除的話後面的json格式就會出錯,而卻夾帶着n等符號,這顯然不是咱們須要的格式和數據,所以在咱們.text()的時候應該把這些html自帶的n,t等去除。使用正則和replace API。
var videoTitle = video.text().replace(/n/g, "").replace(/s/g, "");
拿到咱們須要的資源以後,並不會是一個json對象的形式,所以咱們還須要加工一次,
var courseData = filterChapters(html) let content = courseData.map((o)=>{ return JSON.stringify(o) // JSON.stringify() 方法用於將 JavaScript 值轉換爲 JSON 字符串。 })
獲得咱們真正想要的資源之後,接下來就是保存它了。新建一個index.json文件用來存放咱們的資源。使用nodejs的fs去寫入咱們的數據,這裏簡單介紹下fs,fs應該是node中最經常使用的api了,其中包含了咱們不少須要的操做,好比讀,寫 下載。有興趣的同窗能夠看看文檔fs。咱們引入fs把爬下來的數據寫進咱們的index.json文件夾中
fs.writeFile('./index.json',content, function(err){ //文件路經,寫入的內容,回調函數 if(err) throw new Error ('寫文件失敗'+err); console.log("成功寫入文件") })
大功告成,咱們去看看咱們的成果,打開index.json文件咱們能夠看到咱們拍下來的數據了
是否是咱們須要的數據呢!!!竊喜竊喜。nodejs演技十分的不錯!
koa 是什麼,借用官網的一句話:koa --基於Node.js平臺的下一代web開發框架。
它很小,但擴展性很強。Koa給人一種乾淨利落的感受,體積小、編程方式乾淨。爲何我要用一下他呢,nodejs同樣能夠完成我接下的操做。的確咱們也能夠用creatServer去建立一個服務,可是做爲程序員應該去攝取新知識,尤爲是好的受歡迎的,這樣才能保持與時俱進!其KOA2真的挺簡單,比起node來講。前文已導入了koa,這裏還會直接講如何使用。不懂的同窗我以爲能夠看看koa官網瞭解下基本的使用。
對於一個mock用到快吐的我來講,毫不能忍受爬來的數據又放到mock上。因而開啓咱們的koa2之旅。
const app = new Koa() const staticPath = './static' //靜態文件夾 app.use(static( path.join( __dirname, staticPath) ////設置靜態文件地址,這裏原本想用路由的可是以爲不必啓動。 )) app.use( async ( ctx ) => { //在咱們的頁面輸出hello world,這裏只是爲了演示下koa的入門。咱們訪問咱們的靜態資源在地址欄加/index.json ctx.body = 'hello world' }) app.listen(3000, () => { //啓動一個3000的端口 console.log('[demo] static-use-middleware is starting at port 3000') })
不能跨域訪問,這怎麼搞。爬下的數據弄了半天,被chroml攔截。ajax跨域訪問是一個老問題了,解決方法不少,比較經常使用的是JSONP方法,JSONP方法是一種非官方方法,並且這種方法只支持GET方式,不如POST方式安全。所以咱們選擇在服務器端更改,引用咱們的koa2-cors。
CORS將請求分爲簡單請求和非簡單請求,能夠簡單的認爲,簡單請求就是沒有加上額外請求頭部的get和post請求,而且若是是post請求,請求格式不能是application/json(由於我對這一塊理解不深若是錯誤但願能有人指出錯誤並提出修改意見)。而其他的,put、post請求,Content-Type爲application/json的請求,以及帶有自定義的請求頭部的請求,就爲非簡單請求。簡單請求的配置十分簡單,若是隻是完成響應就達到目的的話,僅需配置響應頭部的Access-Control-Allow-Origin便可
app.use(cors({ origin: function(ctx) { if (ctx.url === '/test') { return false; } return '*'; },
因爲本文重在介紹爬蟲而且我最近在寫一個vue項目就用這個演示下axios的基本請求,想了解更多axios能夠去axios github上理解更多的用法。
methods: { getdata () { axios.get('http://localhost:3000/index.js',{ //訪問咱們建立的端口 dataType: 'json', contentType:"application/json", crossDomain: true, }) .then(function(response){ console.log(response.data); }) .catch(function(err){ console.log(err); }); } }, mounted () { this.getdata() //能夠用async/awiter讓你的請求變得更優雅,這裏就不作處理。主要是太懶了... }
請求完數據,咱們在控制檯打印輸出了咱們的data
引用文字
三者一塊兒的功力實在是太強悍了。讓咱們看到了一出精彩絕倫的好戲。你看到這裏說明你也是想要了解的。那爲何不本身動手實現下,個人項目在我github上,你能夠clone下來,其實併發不了多少時間的。能夠解決之後你數據來源的煩惱,歡樂而不爲呢?你也能夠跟着整篇文章的思路本身實現,期待你更優秀的做品和我分享。歡迎在下方評論以及留言。我是個大三的孩子,(不能說孩子要說學生)最近在找實習公司。但願有推薦的也能夠介紹介紹。下篇文章我會推出個人vue實戰做品。你也能夠關注我,跟我一塊兒學習。樂與分享,收穫友誼。