如何利用Node.js做簡單的圖片爬取
介紹
爬蟲的主要目的是收集互聯網上公開的一些特定數據。利用這些數據我們可以能進行分析一些趨勢對比,或者訓練模型做深度學習等等。本期我們就將介紹一個專門用於網絡抓取的 node.js
包—— node-crawler
,並且我們將用它完成一個簡單的爬蟲案例來爬取網頁上圖片並下載到本地。
node-crawler
是一個輕量級的 node.js
爬蟲工具,兼顧瞭高效與便利性,支持分佈式爬蟲系統,支持硬編碼,支持http前級代理。而且,它完全是由 nodejs
寫成,天生支持非阻塞異步IO,為爬蟲的流水線作業機制提供瞭極大便利。同時支持對 DOM
的快速選擇(可以使用 jQuery
語法),對於抓取網頁的特定部分的任務可以說是殺手級功能,無需再手寫正則表達式,提高爬蟲開發效率。
安裝引入
我們先新建一個項目,在裡面創建index.js作為入口文件。
然後進行爬蟲庫 node-crawler
的安裝。
# PNPM pnpm add crawler # NPM npm i -S crawler # Yarn yarn add crawler
然後用過 require
引入進去。
// index.js const Crawler = require("crawler");
創建實例
// index.js let crawler = new Crawler({ timeout:10000, jQuery:true, }) function getImages(uri) { crawler.queue({ uri, callback: (err, res, done) => { if (err) throw err; } }) }
從現在我們將開始寫一個拿到html頁面的圖片的方法,crawler
實例化後,在其隊列中主要是為瞭寫入鏈接和回調方法。在每個請求處理完畢後將調這個回調函數。
這裡還要說明一下, Crawler
使用瞭 request
庫,所以 Crawler
可供配置的參數列表是 request
庫的參數的超集,即 request
庫中所有的配置在 Crawler
中均適用。
元素捕獲
剛才或許你也看到瞭 jQuery
這個參數,你猜的沒錯,它可以使用 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(); } }) }
可以看到剛才通過 $
來完成對請求中 img
標簽的捕獲。然後我們下面的邏輯去處理補全圖片的鏈接和剝離出名字為瞭後面可以保存取名用。這裡還定義瞭一個數組,它的目的是保存已經捕獲到的圖片地址,如果下次捕獲發現同一個圖片地址,那麼就不再重復處理下載瞭。
以下是掘金首頁html用 $("img") 捕獲到的信息打印:
下載圖片
下載之前我們還要安裝一個 nodejs
包—— axios
,是的你沒看錯,axios
不僅提供給前端,它也可以給後端去使用。但是因為下載圖片要把它處理成數據流,所以把 responseType
設置成 stream
。然後才可以用 pipe
方法保存數據流文件。
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' }) res.data.pipe(fs.createWriteStream(filePath)) }
因為可能圖片很多,所以要統一放在一個文件夾下,就要判斷有沒有這個文件夾如果沒有就創建一個。然後通過 createWriteStream
方法來把獲取到的數據流以文件的形式保存到文件夾裡面。
然後我們可以嘗試一下,比如我們捕獲用一下掘金首頁html下的圖片:
// index.js getImages("https://juejin.cn/")
執行後發現就可以發現已經捕獲到靜態html裡面的所有圖片瞭。
node index.js
結語
到瞭最後,你也可以看到,此代碼可能不適用於SPA(單頁面應用)。由於單頁應用程序中隻有一個 HTML 文件,並且網頁上的所有內容都是動態呈現的,但是萬變不離其宗,不管怎樣,你可以直接處理其數據請求,來收集到想要的信息也未嘗不可。
還有一點要說的是,很多小夥伴處理下載圖片的請求用到瞭 request.js
,當然這樣可以的,甚至代碼量更少,但是,我想說的是這個庫在2020年的時候就已經被棄用瞭,最好換一個一直在更新維護的庫比較好。
到此這篇關於如何利用Node.js做簡單的圖片爬取的文章就介紹到這瞭,更多相關Node.js圖片爬取內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Node.js 中使用fetch 按JSON格式發post請求的問題解析
- Node.js實戰之Buffer和Stream模塊系統深入剖析詳解
- Node.js開發靜態資源服務器
- Node.js全局處理響應並進行異常管理
- nodejs中的http模塊與npm模塊使用