Nodejs中关于抓取图片时候遇到的错误 Unhandled stream error in pipe.
Nodejs中关于抓取图片时候遇到的错误 Unhandled stream error in pipe.
在批量抓取图片的时候,总是会出现如题所示的错误,请有经验的同学指点一二,核心代码如下:
request(searchUrl, function(err, res, body) {
if (!err && res.statusCode == 200) {
var images,
imageUrl,
imageName,
timestamp = new Date().getTime();
mkdirp(filePath);
$ = cheerio.load(body);
images = $('.box img');
images.each(function(i, e) {
imageUrl = e.attribs['src'].replace(/\/t\//, '/pre/');
imageName = timestamp + i + '.jpg';
console.log(imageUrl);
request(imageUrl).pipe(fs.createWriteStream(filePath + "/" + imageName));
});
}
});
在使用 Node.js 抓取图片时遇到 Unhandled stream error in pipe
错误通常是由于流处理过程中出现了问题。这可能是由于网络请求失败、文件路径问题或资源未正确关闭等原因导致的。
解释
当你使用 request
库来获取图片并将其保存到文件系统时,你需要确保所有可能出错的地方都有适当的错误处理。在这个例子中,你没有为 request(imageUrl)
创建的可读流添加错误处理。如果在管道传输过程中发生错误,这个错误将不会被捕获,从而导致 Unhandled stream error
。
示例代码
为了更好地处理错误,我们可以在管道操作中添加错误处理逻辑。这里使用了 request
和 fs
模块,但请注意这些模块已经不再维护。推荐使用更现代的替代方案,例如 node-fetch
和 fs/promises
。
const request = require('request');
const fs = require('fs');
const path = require('path');
const cheerio = require('cheerio');
const mkdirp = require('mkdirp');
const searchUrl = 'http://example.com'; // 替换为实际的URL
const filePath = './images'; // 图片保存目录
request(searchUrl, function (err, res, body) {
if (!err && res.statusCode == 200) {
const $ = cheerio.load(body);
const images = $('.box img');
const timestamp = new Date().getTime();
mkdirp(path.resolve(__dirname, filePath), err => {
if (err) throw err;
images.each((i, e) => {
const imageUrl = e.attribs['src'].replace(/\/t\//, '/pre/');
const imageName = `${timestamp}-${i}.jpg`;
console.log(`Downloading ${imageUrl} to ${filePath}/${imageName}`);
const writeStream = fs.createWriteStream(path.join(filePath, imageName));
request(imageUrl)
.on('error', (err) => {
console.error(`Error downloading image: ${err.message}`);
})
.pipe(writeStream)
.on('error', (err) => {
console.error(`Error writing image to file: ${err.message}`);
writeStream.end(); // 确保关闭写入流
})
.on('finish', () => {
console.log(`Image saved: ${filePath}/${imageName}`);
});
});
});
} else {
console.error('Error fetching the webpage:', err);
}
});
关键点
- 错误处理:在
request
和writeStream
中都添加了错误处理。 - 文件路径:使用
path
模块来确保生成正确的文件路径。 - 资源管理:确保在流操作完成或出错时正确关闭资源。
通过这种方式,你可以更健壮地处理抓取图片过程中的各种错误情况。
我也碰上了。用pipe的时候就容易报错。后来改成这么写就没问题了
<pre>
request({uri: imgSrc, encoding: ‘binary’}, function (error, response, body) {
if (!error && response.statusCode == 200) {
fs.writeFile(dest, body, ‘binary’, function (err) {
if (err) {console.log(err);}
});
}
});
</pre>
我对node理解也不深,还是希望其他人能解释下pipe出错的原因
http://isawsomecode.tumblr.com/post/24371068694/fs-createreadstream-should-be-re-engineered 会不会是这种原因。 在fs.createWriteStream的时候on一下error呢。
确实在https://github.com/joyent/node/blob/master/lib/stream.js 代码的 90 ~ 97行:
// don't leave dangling pipes when there are errors.
function onerror(er) {
cleanup();
if (EE.listenerCount(this, 'error') === 0) {
throw er; // Unhandled stream error in pipe.
}
}
不考虑因为这是网络问题导致的?
把 on(‘error’, fn) 放在 pipe 之前,才能捕捉到 pipe 的错误
在处理文件流时,可能会因为某些原因导致管道(pipe)操作失败。常见的问题包括网络请求超时、请求的图片不存在或者文件路径不正确等。
你可以尝试在管道操作前添加错误处理逻辑,确保在出现任何问题时能够捕获到错误并进行相应的处理。以下是改进后的代码示例:
const request = require('request');
const fs = require('fs');
const mkdirp = require('mkdirp');
const searchUrl = 'YOUR_SEARCH_URL';
const filePath = 'YOUR_FILE_PATH';
request(searchUrl, function(err, res, body) {
if (!err && res.statusCode == 200) {
const $ = require('cheerio').load(body);
const images = $('.box img');
mkdirp(filePath, err => {
if (err) throw err;
images.each((i, e) => {
const imageUrl = e.attribs['src'].replace(/\/t\//, '/pre/');
const imageName = new Date().getTime() + i + '.jpg';
request(imageUrl)
.on('error', err => console.error(`Error downloading image ${imageUrl}:`, err))
.pipe(fs.createWriteStream(`${filePath}/${imageName}`))
.on('error', err => console.error(`Error writing image ${imageUrl} to disk:`, err));
});
});
}
});
上述代码做了以下改进:
- 添加了
mkdirp
的错误处理。 - 在
request(imageUrl)
上添加了错误处理,以便捕获下载图片时可能发生的错误。 - 在
fs.createWriteStream
上添加了错误处理,以捕获写入文件时可能出现的问题。
通过这些改进,可以更好地调试和定位错误,从而提高程序的健壮性。