NodeJS爬取墨刀上的设计图片
背景
设计人员分享了一个墨刀的原型图,但是给的是只读权限,无法下载其中的素材;开发时想下载里面的一张动图,通过浏览器的F12工具在页面结构找到了图片地址。
但是浏览器直接访问后发现没权限: Nginx
的 403
页面。。然后就想用其他方式下载这个图片。
失败的尝试:通过浏览器请求另存为图片
从前面的403报错可以知道,访问这个图片的链接应该需要带头信息,那就先看下网络中的这个请求的头信息(我这里用图片作为条件过滤了一下),找见请求后右键有个另存为图片,以为这就大功告成了,但是保存后发现大小只有1M(1024KB,而从浏览器的请求中可以看到,实际的文件大小差不多10M),这很可能是浏览器哪里做了限制,导致下载的图片不是原图或者不完整。
成功的尝试:NodeJS发送Fetch请求
在开发者工具中的网络请求右键中,还有一个选项:在控制台中Fetch,点击之后会在控制台中生成一段代码,用于发送请求获取图片,并且带了头信息。
看到这个代码,我立即就联想到可以通过 Node.js
来发送请求,然后下载保存图片,说干就干,以下是完整代码。
const fs = require("fs");const downloadFile = (async (url, path) => {const res = await fetch("https://modao.cc/x/y/z.gif", {"credentials": "include","headers": {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0","Accept": "image/avif,image/webp,*/*","Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2","Sec-Fetch-Dest": "image","Sec-Fetch-Mode": "no-cors","Sec-Fetch-Site": "same-origin","Pragma": "no-cache","Cache-Control": "no-cache"},"referrer": "https://modao.cc/abc/opq&from=sharing","method": "GET","mode": "cors"});fs.writeFile(path, Buffer.from(await res.arrayBuffer()), 'binary', function(err) {if (err) throw err;console.log("OK");});
});downloadFile(1, "./1.gif")
以上代码主要用到了 Node.js
的 fetch
方法来发送资源请求,以及 fs
模块来存储图片,简单直接有效。
可能遇到的问题
不过,通过上述方式并不能下载所有的素材,有的图片下载返回了状态码: 304 Not Modified
;我们知道,如果服务器返回状态码为 304 Not Modified
,这意味着请求的资源在服务器上没有发生变化,服务器告诉客户端可以使用缓存的版本。这是一种优化机制,可以减少网络流量和提高性能。
当浏览器或其他客户端首次请求资源时,服务器会返回资源的完整内容和一个响应头(Response Header),其中包含一个叫做"ETag"的字段。 ETag
是一个唯一标识符,表示资源的版本。当客户端再次请求相同的资源时,会在请求头(Request Header)中包含一个叫做"If-None-Match"的字段,该字段的值就是上次请求返回的 ETag
值。
如果服务器收到了带有"If-None-Match"字段的请求,并且发现资源的 ETag
值与请求头中的值相匹配,服务器就会返回 304 Not Modified
状态码,告诉客户端可以使用缓存的版本。这样可以节省带宽和服务器资源,因为客户端可以直接从缓存中获取资源,而不需要重新下载。
解决方法:更新请求头部,尝试在 fetch
请求中添加 Cache-Control: no-cache
头部,这将告诉服务器不使用缓存版本,强制返回实际的资源内容。或者直接去掉浏览器生成的头信息中的 If-Modified-Since
与 If-None-Match
:
"If-Modified-Since": "Fri, 21 Jul 2023 07:05:31 GMT","If-None-Match":"\"64ba2e3b-14711"\"
const fs = require("fs");const downloadFile = (async (url, path) => {const res = await fetch("https://modao.cc/x/y/z.png", {"credentials": "include","headers": {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0","Accept": "image/avif,image/webp,*/*","Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2","Sec-Fetch-Dest": "image","Sec-Fetch-Mode": "no-cors","Sec-Fetch-Site": "same-origin",},"referrer": "https://modao.cc/abc/opq&from=sharing","method": "GET","mode": "cors"});fs.writeFile(path, Buffer.from(await res.arrayBuffer()), 'binary', function(err) {if (err) throw err;console.log("OK");});
});downloadFile(2, "./2.png")
小总结
以上记录了使用 NodeJS
爬取墨刀上的设计图片的过程。
-
当使用
Node.js
的爬虫fetch
请求时,返回状态码304 Not Modified
表示请求的资源在服务器上没有发生变化,因此服务器不会返回实际的资源内容,而是告诉客户端可以使用缓存的版本。 -
这种情况通常发生在客户端发送了一个带有
If-Modified-Since
或If-None-Match
头部的请求,这些头部包含了之前请求时服务器返回的资源的相关信息,用于判断资源是否发生了变化。 -
要解决这个问题,可以尝试在
fetch
请求中添加Cache-Control: no-cache
头部,这将告诉服务器不使用缓存版本,强制返回实际的资源内容。
相关文章:

NodeJS爬取墨刀上的设计图片
背景 设计人员分享了一个墨刀的原型图,但是给的是只读权限,无法下载其中的素材;开发时想下载里面的一张动图,通过浏览器的F12工具在页面结构找到了图片地址。 但是浏览器直接访问后发现没权限: Nginx 的 403 页面。。…...

linux--
一、crond 任务调度 1、原理示意图 2、crontab 进行定时任务的设置 2.1. 概述 任务调度,是指系统在某个时间执行的特定的命令或程序。任务调度分类: 系统工作: 有些重要的工作必须周而复始地执行。如病毒扫描等 个别用户工作:个别用户可能希望执行某些…...

conda虚拟环境笔记收录
1、安装conda 增加执行权限: chmod x Anaconda3-2023.03-1-Linux-x86_64.sh 开始执行:./Anaconda3-2023.03-1-Linux-x86_64.sh2、查看版本 conda --version3、查看当前虚拟环境 虚拟环境和全局环境有前缀可见 如果不进行设置,重新启动就变成…...

RGB-T Salient Object Detection via Fusing Multi-Level CNN Features
ADFC means ‘adjacent-depth feature combination’,MGF means ‘multi-branch group fusion’,JCSA means ‘joint channel-spatial attention’,JABMP means ‘joint attention guided bi-directional message passing’ 作者未提供代…...

安卓开发实例:方向传感器
调用手机的方向传感器,X轴,Y轴,Z轴的数值 activity_sensor.xml <?xml version"1.0" encoding"utf-8"?> <androidx.constraintlayout.widget.ConstraintLayoutxmlns:android"http://schemas.android.c…...

[论文笔记]GTE
引言 今天带来今年的一篇文本嵌入论文GTE, 中文题目是 多阶段对比学习的通用文本嵌入。 作者提出了GTE,一个使用对阶段对比学习的通用文本嵌入。使用对比学习在多个来源的混合数据集上训练了一个统一的文本嵌入模型,通过在无监督预训练阶段和有监督微调阶段显著增加训练数…...
Prometheus字段解析
官方文档::Configuration | Prometheus 1、全局配置指定在所有其他配置上下文中有效的参数。它们还用作其他配置部分的默认值。 global:# How frequently to scrape targets by default.默认情况下,定期抓取目标的频率是多久一次?…...

msigdbr hallmarks gsea broad研究所
使用msigdbr r包 #BiocManager::install("msigdb") #https://www.gsea-msigdb.org/gsea/msigdb #https://cran.r-project.org/web/packages/msigdbr/vignettes/msigdbr-intro.html #https://bioconductor.org/packages/release/data/experiment/vignettes/msigdb/ins…...

理解V3中的proxy和reflect
现有如下面试题 结合GeexCode和Gpt // 这个函数名为onWatch,接受三个参数obj、setBind和getlogger。 // obj是需要进行监视的对象。 // setBind是一个回调函数,用于在设置属性时进行绑定操作。 // getlogger是一个回调函数,用于在获取属性时…...

实现寄生组合继承
寄生组合继承是一种继承方式,它通过组合使用构造函数继承和原型继承的方式,实现了高效而且正确的继承方式。 具体实现步骤如下: ① 定义一个父类,实现其属性和方法: function Person(name) {this.name namethis.age…...
ARM 账号注册报错 The claims exchange ‘Salesforce-UserWriteUsingEmail‘
ARM 账号注册报错 The claims exchange ‘Salesforce-UserWriteUsingEmail’ 参考:ARM 账号注册报错 The claims exchange ‘Salesforce-UserWriteUsingEmail’ specified in step ‘14’ returned HTTP error response with Code ‘BadRequest’ and Reason ‘Bad …...

笔记:电子设备接地,接的到底是什么地?
电路中有“地”,设备中有“地”;都是“地”,此地非彼地。 混淆的原因 有些混淆,是以为中文翻译造成的,英文所有Ground都统一翻译为“地”; 例1:英文Circuit Ground,应该翻译为电路…...

PY32F002A系列单片机:高性价比、低功耗,满足多样化应用需求
PY32F002A系列微控制器是一款高性能、低功耗的MCU,它采用32位ARM Cortex-M0内核,最高工作频率达到24MHz,提供了强大的计算能力。此外,PY32F002A拥有最大20Kbytes的flash存储器和3Kbytes的SRAM,为简单的数据处理提供了充…...
头歌的数据库的第三次作业的答案
目录 MySQL-安全性控制 第1关:用户和权限 第2关:用户、角色与权限 MySQL-触发器 第1关:为投资表property实现业务约束规则-根据投资类别分别引用不同表的主码 MySQL-数据的插入、修改与删除(Insert,Update,Delete) 第1关:插…...
前端3D规划
学习基础的3D概念:这包括向量、矩阵、几何、光照和材质等基本3D图形学的概念。这些是理解和使用3D技术的基础。学习WebGL:WebGL是一种在浏览器中实现3D图形的技术,它是OpenGL的Web版本,可以直接在浏览器中使用。学习WebGL可以帮助…...

appium操控微信小程序的坑
appium操控微信小程序的坑 打不开启动页面driver的context只有NATIVE_APP小程序上元素找不到 我打算使用appium操控微信小程序,只要能够获取到小程序的页面元素就算成功。下面都是我遇到的问题。 打不开启动页面 以下是我的appium的配置参数和代码: de…...

6 个最佳 Windows 免费磁盘分区管理器
几乎所有新的笔记本电脑和 PC 都只有一个分区 C:\,与安装了 Windows 的分区相同。不太精通技术的用户开始按照计算机呈现给他们的方式使用计算机;他们将所有文档、个人文件(例如图片、歌曲、电影等)放在同一个分区上。整个驱动器上…...

【Leetcode】【每日一题】【简单】2558. 从数量最多的堆取走礼物
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/take-gifts-from-the-richest-pi…...
LeetCode 每日一题 2023/10/23-2023/10/29
记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步 目录 10/23 2678. 老人的数目10/24 1155. 掷骰子等于目标和的方法数10/25 2698. 求一个整数的惩罚数10/26 2520. 统计能整除数字的位数10/27 1465. 切割后面积最大的蛋糕10/28 2…...
Android:Installed Build Tools revision 33.0.2 is corrupted.
Remove and install again using the SDK Manager. 使用33.0.2及以上版本的build-tools编译Android应用时。 有些人会按照提示去SDK Manager中重新安装build tools,然后发现这样做是无用的 编译时会收到:Build-tool 33.0.2 is missing DX at D:\Sdk\b…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...