2018年5月2日 星期三

用node js與amazon S3同步資料

前言:

最近專案上有需求,需要把專案資料夾底下的某個資料夾與amazon S3的某個資料夾同步,一開始看到有人使用go寫了相關功能,小編就想說javascript都快一統天下了,沒理由辦不到啊!!所以去載了s3的node js sdk來看,發現密密麻麻的......
於是開始尋求比較簡單的做法,無意中發現了s3-sync-aws這個套件最接近我想要的功能,但唯一缺點是無法指定我要cpoy到哪個資料夾下面,所以小編fork了這個專案,再稍微改編一下成了jac-s3-sync-aws,多了一個dest參數可以塞,已達到小編要的效果。

效果:

以下這範例程式碼,可以把專案中./resource/資料夾下的所有資料直接同步到aws bucket/resource/上面(這裡指的同步,其實是增量提交,如果有刪除的檔案,s3上面還會依舊保存,所以如果有大量異動檔案,請記得定時清理s3)

另外如果aws會自動備份,分裂,等動作,同步就會被判斷為不同檔案,所以會全部掃描一次(但只會掃描,不會真的上傳),小編實際上測試用程式同步會比cyberduck速度快上將近一倍,當然實際情況因人因機器而異啦,那廢話不多說,我們就來看程式吧。

var path = require('path')
, level = require('level')
, s3sync = require('jac-s3-sync-aws')
, readdirp = require('readdirp')
require('dotenv').config()

var db = level(path.join(__dirname, '../dist', 'cache'))

var files = readdirp({
root: './resource', // 要上傳的資料夾
directoryFilter: ['!.git', '!cache'] // 忽略的資料夾
})

var bucket = 'bucket',
index = 0

var uploader = s3sync(db, {
key: process.env.AWS_ACCESS_KEY,
secret: process.env.AWS_SECRET_KEY,
bucket: bucket, // bucket
dest: 'resource', // 只掉的資料夾
concurrency: 100 // 同時上除檔案數
}).on('data', function (file) {
if (file.fresh) { // 資料比對有異動才執行
console.log(`${file.fullPath}\n->${file.url}\nindex:${index++}\n`)
}
})

files.pipe(uploader)

2018年1月22日 星期一

使用node js跟puppeteer初學爬蟲

主題
發現好久沒更新網誌了,去年工作太忙,卻也學習到了不少東西,希望陸續能跟各位進行分享。希望啦.....

今天回去看以前的網誌,發現......媽的字好多啊!!好吧我平常內心戲,加上本來話就比較多,難怪觀看人數持續低迷==好啦我以後會少說些話。

另外這只篇是筆記文,所以不會跟大家太過申論工具的原理,我也不知道。小編是個不求甚解的攻城屍,大部分情況都是會用工具就好,該踩坑就踩坑,該google就google。所以!今天就是要跟各位介紹一款google官方推出的爬蟲工具puppeteer,這同時也是好用的自動化測試工具。

原因:
其實小編一開始接觸的是nightmare.js,寫法像是jQuery那樣,一直obj.goto(src).wait(300).type()....(小編忘記這種寫法叫什麼了,就是function處理完之後return this這種寫法,只要事情還沒處理完就可以一直點下去,知道這寫法叫什麼名字的人也歡迎留言告訴我)

這東西有什麼好處呢?易讀性佳,api也沒有很多,學習容易。
但小編認為唯一的缺點,也是我最終棄用的原因:他沒有promise,所以沒辦法在前端取到資料,即時傳回後端處理(有些東西畢竟還是要後端處理比較容易)

所以再次搜索下才發現了這套功能強大好用,完全可以取代nightmare的工具puppeteer,再搭配es7的async await 寫法,完全變成一套無懈可擊的工具。因為他的核心是用webkit撰寫,可以進行瀏覽器的操作,特別它又是google開發的,可以直接運行chromium,所以任何瀏覽器你所想得到的行為,無論是每天那些繁瑣又重複的抓取報表,或者是爬文,或是機器人等行為,都可以用此自動化實現,也可以搭配一些圖形辨識api做到一些.....你想做的事。

事前準備:
1.打開你的命令提示字元,鍵入:
npm install puppeteer

好了,完成了,可以開始寫程式了。
const puppeteer = require('puppeteer')
;(async () => {
  browser = await puppeteer.launch({
    headless: false // 開啟瀏覽器
  })


  page = await browser.newPage()
  await page.goto('https://www.google.com') // 打開google頁面
  await page.waitFor('#lst-ib') // 等待搜尋bar的出現
  await page.type('#lst-ib', 'test') // 在搜尋bar鍵入 'test'
  await page.keyboard.press('Enter') //鍵盤按下 Enter
  await page.waitFor('._NId') // 等待查詢列表的出現
  const contentHandle = await page.$('._NId') // 取的查詢列表DOM
  const html = await page.evaluate(content => {
    return content.getElementsByClassName('g')[0].innerHTML // 取得第一筆
  }, contentHandle)
  console.log(html) // 印出html
  await page.wait(30000) // 等待30秒,方便觀察
  await browser.close() // 關閉瀏覽器
})()

小結:
結束了!!沒錯,小編的文章一向說明文字多過於程式碼==
上述一隻簡單的程式就可以模擬網頁打開google頁面並搜尋test,且取得返回值。
puppeteer真的可以算是簡單好用的工具。唯一小缺點就是程式碼會有一堆await,畢竟每個行為都是異步,必須等待回傳值。不過相較於缺點,非常直觀地模擬著瀏覽器操作行為此強大功能應該瑕不掩瑜。
完成了小編小時候希望去破解別人無名當一名很厲害的駭客或爬蟲,用程式幫助到人減少繁瑣事務纏身的夢想。
以上就是這次的分享,我們有緣下次再見了。

備註:
如果你在linux上遇到了些麻煩,可以參考以下網址
https://segmentfault.com/a/1190000011382062