如何使用Node進(jìn)行爬?。肯旅姹酒恼聨Т蠹伊牧氖褂肗ode.js開發(fā)一個(gè)簡單圖片爬取功能,希望對(duì)大家有所幫助!
爬蟲的主要目的是收集互聯(lián)網(wǎng)上公開的一些特定數(shù)據(jù)。利用這些數(shù)據(jù)我們可以能進(jìn)行分析一些趨勢(shì)對(duì)比,或者訓(xùn)練模型做深度學(xué)習(xí)等等。本期我們就將介紹一個(gè)專門用于網(wǎng)絡(luò)抓取的 node.js
包—— node-crawler
,并且我們將用它完成一個(gè)簡單的爬蟲案例來爬取網(wǎng)頁上圖片并下載到本地。
正文
node-crawler
是一個(gè)輕量級(jí)的 node.js
爬蟲工具,兼顧了高效與便利性,支持分布式爬蟲系統(tǒng),支持硬編碼,支持http前級(jí)代理。而且,它完全是由 nodejs
寫成,天生支持非阻塞異步IO,為爬蟲的流水線作業(yè)機(jī)制提供了極大便利。同時(shí)支持對(duì) DOM
的快速選擇(可以使用 jQuery
語法),對(duì)于抓取網(wǎng)頁的特定部分的任務(wù)可以說是殺手級(jí)功能,無需再手寫正則表達(dá)式,提高爬蟲開發(fā)效率。
安裝引入
我們先新建一個(gè)項(xiàng)目,在里面創(chuàng)建index.js作為入口文件。
然后進(jìn)行爬蟲庫 node-crawler
的安裝。
# PNPM pnpm add crawler # NPM npm i -S crawler # Yarn yarn add crawler
然后用過 require
引入進(jìn)去。
// index.js const Crawler = require("crawler");
創(chuàng)建實(shí)例
// index.js let crawler = new Crawler({ timeout:10000, jQuery:true, }) function getImages(uri) { crawler.queue({ uri, callback: (err, res, done) => { if (err) throw err; } }) }
從現(xiàn)在我們將開始寫一個(gè)拿到html頁面的圖片的方法,crawler
實(shí)例化后,在其隊(duì)列中主要是為了寫入鏈接和回調(diào)方法。在每個(gè)請(qǐng)求處理完畢后將調(diào)這個(gè)回調(diào)函數(shù)。
這里還要說明一下, Crawler
使用了 request
庫,所以 Crawler
可供配置的參數(shù)列表是 request
庫的參數(shù)的超集,即 request
庫中所有的配置在 Crawler
中均適用。
元素捕獲
剛才或許你也看到了 jQuery
這個(gè)參數(shù),你猜的沒錯(cuò),它可以使用 jQuery
的語法去捕獲 DOM
元素的。
// index.js let data = [] function getImages(uri) { crawler.queue({ uri, callback: (err, res, done) => { if (err) throw err; let $ = res.$; try { let $imgs = $("img"); Object.keys($imgs).forEach(index => { let img = $imgs[index]; const { type, name, attribs = {} } = img; let src = attribs.src || ""; if (type === "tag" && src && !data.includes(src)) { let fileSrc = src.startsWith('http') ? src : `https:${src}` let fileName = src.split("/")[src.split("/").length-1] downloadFile(fileSrc, fileName) // 下載圖片的方法 data.push(src) } }); } catch (e) { console.error(e); done() } done(); } }) }
可以看到剛才通過 $
來完成對(duì)請(qǐng)求中 img
標(biāo)簽的捕獲。然后我們下面的邏輯去處理補(bǔ)全圖片的鏈接和剝離出名字為了后面可以保存取名用。這里還定義了一個(gè)數(shù)組,它的目的是保存已經(jīng)捕獲到的圖片地址,如果下次捕獲發(fā)現(xiàn)同一個(gè)圖片地址,那么就不再重復(fù)處理下載了。
以下是掘金首頁html用 $("img")
捕獲到的信息打?。?/p>
下載圖片
下載之前我們還要安裝一個(gè) nodejs
包—— axios
,是的你沒看錯(cuò),axios
不僅提供給前端,它也可以給后端去使用。但是因?yàn)橄螺d圖片要把它處理成數(shù)據(jù)流,所以把 responseType
設(shè)置成 stream
。然后才可以用 pipe
方法保存數(shù)據(jù)流文件。
const { default: axios } = require("axios"); const fs = require('fs'); async function downloadFile(uri, name) { let dir = "./imgs" if (!fs.existsSync(dir)) { await fs.mkdirSync(dir) } let filePath = `${dir}/${name}` let res = await axios({ url: uri, responseType: 'stream' }) let ws = fs.createWriteStream(filePath) res.data.pipe(ws) res.data.on("close",()=>{ ws.close(); }) }
因?yàn)榭赡軋D片很多,所以要統(tǒng)一放在一個(gè)文件夾下,就要判斷有沒有這個(gè)文件夾如果沒有就創(chuàng)建一個(gè)。然后通過 createWriteStream
方法來把獲取到的數(shù)據(jù)流以文件的形式保存到文件夾里面。
然后我們可以嘗試一下,比如我們捕獲用一下掘金首頁html下的圖片:
// index.js getImages("https://juejin.cn/")
執(zhí)行后發(fā)現(xiàn)就可以發(fā)現(xiàn)已經(jīng)捕獲到靜態(tài)html里面的所有圖片了。
node index.js
結(jié)語
到了最后,你也可以看到,此代碼可能不適用于SPA(單頁面應(yīng)用)。由于單頁應(yīng)用程序中只有一個(gè) HTML 文件,并且網(wǎng)頁上的所有內(nèi)容都是動(dòng)態(tài)呈現(xiàn)的,但是萬變不離其宗,不管怎樣,你可以直接處理其數(shù)據(jù)請(qǐng)求,來收集到想要的信息也未嘗不可。
還有一點(diǎn)要說的是,很多小伙伴處理下載圖片的請(qǐng)求用到了 request.js
,當(dāng)然這樣可以的,甚至代碼量更少,但是,我想說的是這個(gè)庫在2020年的時(shí)候就已經(jīng)被棄用了,最好換一個(gè)一直在更新維護(hù)的庫比較好。