node.js突破nginx防盜鏈機(jī)制,下載圖片案例分析 原創(chuàng)
問題
今天項(xiàng)目需求要求采集幾個網(wǎng)站的信息,包括一些區(qū)塊鏈統(tǒng)計(jì)圖表之類的信息。
筆者使用的是node.js+axios庫發(fā)送get請求來獲取在圖片,下載到本地。測試代碼如下:
import fs from 'fs'; import path from 'path'; import http from 'http'; import https from 'https'; const __dirname = path.resolve(); let filePath = path.join(__dirname,'/imgtmp/'); async function downloadfile(url,filename,callback){ try { let ext = path.extname(url); console.log('下載的文件名:',filename) let mod = null;//http、https 別名 if(url.indexOf('https://')!==-1){ mod = https; }else{ mod = http; } const req = mod.get(url, { headers:{ "Content-Type": "application/x-www-form-urlencoded" } },(res)=>{ let writePath = ''; writePath = filePath + '/' + filename; const file = fs.createWriteStream(writePath) res.pipe (file) file.on ("error", (error) => { console.log (`There was an error writing the file. Details: `,error) return false; }) file.on ("close", () => { callback (filename) }) file.on ('finish', () => { file.close () console.log ("Completely downloaded.") }) }) req.on ("error", (error) => { console.log (`Error downloading file. Details: $ {error}`) }) } catch (error) { console.log('圖片下載失??!',error); } } let url = 'https://xx.xxxx.com/d/file/zxgg/a2cffb8166f07c0232eca49f8c9cc242.jpg';//圖片url let filename = path.basename(url); await downloadfile(url,filename,()=>{ console.log(filename,"文件已下載成功"); })
運(yùn)行代碼,圖示文件下載成功!
然而當(dāng)筆者打開圖片一看,就傻眼了~圖片顯示損壞,再看大小,只有304字節(jié)~
目測應(yīng)該是圖片保存了一些錯誤信息,于是用editplus以文本形式打開該圖片,果然看到了錯誤信息~
解決方法
百度了一下,確定是圖片nginx服務(wù)器Referer防盜鏈設(shè)置,于是繼續(xù)百度,找到了問題的關(guān)鍵~
谷歌瀏覽器打開網(wǎng)址,在控制臺上看到了這段Referer信息:
對方的網(wǎng)站在Referer設(shè)置的就是他的網(wǎng)址,于是改進(jìn)代碼,在headers中加入Referer參數(shù)"referer":'https://www.xxxx.com/'
:
import fs from 'fs'; import path from 'path'; import http from 'http'; import https from 'https'; const __dirname = path.resolve(); let filePath = path.join(__dirname,'/imgtmp/'); async function downloadfile(url,filename,callback){ try { let ext = path.extname(url); console.log('下載的文件名:',filename) let mod = null;//http、https 別名 if(url.indexOf('https://')!==-1){ mod = https; }else{ mod = http; } const req = mod.get(url, { headers:{ "Content-Type": "application/x-www-form-urlencoded", "referer":'https://www.xxxx.com/' } },(res)=>{ let writePath = ''; writePath = filePath + '/' + filename; const file = fs.createWriteStream(writePath) res.pipe (file) file.on ("error", (error) => { console.log (`There was an error writing the file. Details: `,error) return false; }) file.on ("close", () => { callback (filename) }) file.on ('finish', () => { file.close () console.log ("Completely downloaded.") }) }) req.on ("error", (error) => { console.log (`Error downloading file. Details: $ {error}`) }) } catch (error) { console.log('圖片下載失??!',error); } } let url = 'https://xx.xxxx.com/d/file/zxgg/a2cffb8166f07c0232eca49f8c9cc242.jpg';//圖片url let filename = path.basename(url); await downloadfile(url,filename,()=>{ console.log(filename,"文件已下載成功"); })
再次運(yùn)行代碼,圖片文件下載成功,打開顯示一切正常!
后記
筆者又測試了另一種實(shí)現(xiàn)方法,即使用playwright調(diào)用瀏覽器打開頁面,再使用await page.locator('selector路徑').screenshot({ path: 'image圖片保存路徑'});
將圖片網(wǎng)頁截圖保存下載。
對比了一番,發(fā)現(xiàn)使用playwright截圖的方法需要在遍歷圖片元素的時候根據(jù)當(dāng)前元素逆向獲取parentNode節(jié)點(diǎn)以及遍歷childNodes節(jié)點(diǎn),算法相對比較復(fù)雜!而且screenshot函數(shù)截圖的效果也會比原圖略顯模糊,因此推薦使用axios傳遞Referer參數(shù)的方法獲取原圖。
PS:方法二的調(diào)試過程中寫了一段逆向遍歷selector的函數(shù),提供給大家參考,如有不足之處,歡迎指正~
/** * 獲取selector */ function getSelectorPath(element) { if (!!element.id !== false) { return '#' + element.id; } if (element === document.body && !!element) { return element.tagName.toLowerCase(); } let ix = 0; const siblings = element.parentNode?.childNodes; for (let i = 0; i < siblings?.length; i++) { const sibling = siblings[i]; if (sibling.innerHTML === element.innerHTML && !!element.parentNode) { return `${getSelectorPath(element.parentNode)} > ${element.tagName.toLowerCase()}:nth-child(${ix + 1})`; } if (sibling.nodeType === 1) { ix++; } } }
- nginx利用referer指令實(shí)現(xiàn)防盜鏈配置
- Nginx防盜鏈的配置方法
- Nginx服務(wù)器下防盜鏈的方法介紹
- Nginx圖片防盜鏈配置實(shí)例
- 配置Nginx的防盜鏈的操作方法
- nginx配置防盜鏈的三種實(shí)現(xiàn)方式總結(jié)
- node+axios實(shí)現(xiàn)下載外網(wǎng)文件到本地
- nodejs連接ftp上傳下載實(shí)現(xiàn)方法詳解【附:踩坑記錄】
- nodejs實(shí)現(xiàn)生成文件并在前端下載
- Node.js實(shí)現(xiàn)下載文件的兩種實(shí)用方式
- Node.js實(shí)現(xiàn)批量下載圖片簡單操作示例
相關(guān)文章
Node.js調(diào)用java之node-java問題
這篇文章主要介紹了Node.js調(diào)用java之node-java問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10詳解Node.js開發(fā)中的express-session
express-session 是基于express框?qū)iT用于處理session的中間件,本篇文章主要介紹了詳解Node.js開發(fā)中的express-session,有興趣的可以了解一下2017-05-05nodejs基礎(chǔ)之buffer緩沖區(qū)用法分析
這篇文章主要介紹了nodejs基礎(chǔ)之buffer緩沖區(qū)用法,結(jié)合實(shí)例形式分析了buffer緩沖區(qū)的概念、功能、創(chuàng)建、讀寫等相關(guān)操作技巧,需要的朋友可以參考下2018-12-12nodejs與瀏覽器中全局對象區(qū)別點(diǎn)總結(jié)
在本篇文章里小編給大家整理的是一篇關(guān)于nodejs與瀏覽器中全局對象區(qū)別點(diǎn)總結(jié)內(nèi)容,對此有需要的朋友們可以學(xué)習(xí)下。2021-12-12詳解如何使用Node.js編寫命令工具——以vue-cli為例
本篇文章主要介紹了如何使用Node.js編寫命令工具——以vue-cli為例,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06nodejs dgram模塊廣播+組播的實(shí)現(xiàn)示例
這篇文章主要介紹了nodejs dgram模塊廣播+組播的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11nodejs中實(shí)現(xiàn)sleep功能實(shí)例
這篇文章主要介紹了nodejs中實(shí)現(xiàn)sleep功能實(shí)例,本文講解了sleep功能的開發(fā)過程和使用效果及性能測試,需要的朋友可以參考下2015-03-03基于 Node 實(shí)現(xiàn)簡易 serve靜態(tài)資源服務(wù)器的示例詳解
靜態(tài)資源服務(wù)器(HTTP 服務(wù)器)可以將靜態(tài)文件(如 js、css、圖片)等通過 HTTP 協(xié)議展現(xiàn)給客戶端。本文介紹如何基于 Node 實(shí)現(xiàn)一個簡易的靜態(tài)資源服務(wù)器,感興趣的朋友一起看看吧2022-06-06