我正在Nodejs中构建一些Web爬虫。刮板可以做的一件事就是下载图像。一切都很好,直到我尝试抓取一个站点,该站点的图像在url中不包含文件扩展名,例如:https://example.com/images/someimagewithoutextension
这是我正在使用的小型库中的一些代码,用于下载和保存图像:
options.encoding = null
request(options, (err, res, body) => {
if (err) {
return onError(err, done)
}
if (body && (res.statusCode === 200 || res.statusCode === 201)) {
if (!path.extname(options.dest)) {
options.dest = path.join(options.dest, path.basename(options.url))
}
fs.writeFile(options.dest, body, 'binary', (err) => {
if (err) {
return onError(err, done)
}
if (typeof done === 'function') {
done(false, options.dest, body)
}
})
}
因此,当图片网址缺少扩展名时,我会收到如下错误:
错误:ENOENT:没有这样的文件或目录,请打开'C:\ Users \ someuser \ Desktop \ nodescraper \ images \ somefilename不带扩展名'
当我console.log()响应的“主体”时,我得到了一些Buffer数组(因此我无法检查mime类型或类似内容),并且据我了解,这表示流。当我从请求配置中删除encoding:null时,我得到了一组字符,但是节点实际上崩溃了。
我如何保存此类图像?
答案 0 :(得分:1)
来自node.js docs:
ENOENT(没有这样的文件或目录):fs操作通常引发该信息,以指示指定路径名的组件不存在-给定路径找不到任何实体(文件或目录)。
此外,如果文件名包含任何restricted characters(例如?),则可能会发生此错误,因此建议删除或替换这些字符以确保您的应用正常运行。在npm上检查sanitize-filename软件包。
HTTP Content-Type响应标头包含响应正文的mime-type。因此,您可以使用它来检测要下载的文件扩展名。例如,如果获得的内容类型为 image / jpeg ,则文件扩展名可以为 .jpeg 。 npm上还有一堆libraries,可以将mime类型转换为文件扩展名。
const { writeFile } = require('fs');
const { extension } = require('mime-types');
const { basename, extname, join } = require('path');
const request = require('request');
const sanitize = require('sanitize-filename');
const dest = join(__dirname, 'images');
const url = '<URL>';
request({ url, encoding: null }, (error, response, body) => {
if (error || response.statusCode < 200 || response.statusCode >= 300) {
console.error('Request failed!');
return;
}
let fileName = join(dest, sanitize(basename(url)));
if (!extname(fileName)) {
const contentType = response.headers['content-type'];
const ext = extension(contentType);
if (ext) {
fileName += `.${ext}`;
} else {
console.error('Cannot detect file extension!');
}
}
writeFile(fileName, body, (err) => {
if (err) {
console.error(err);
return;
}
console.log('done');
});
});