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));
    }); 
  }
}); 

8 回复

在使用 Node.js 抓取图片时遇到 Unhandled stream error in pipe 错误通常是由于流处理过程中出现了问题。这可能是由于网络请求失败、文件路径问题或资源未正确关闭等原因导致的。

解释

当你使用 request 库来获取图片并将其保存到文件系统时,你需要确保所有可能出错的地方都有适当的错误处理。在这个例子中,你没有为 request(imageUrl) 创建的可读流添加错误处理。如果在管道传输过程中发生错误,这个错误将不会被捕获,从而导致 Unhandled stream error

示例代码

为了更好地处理错误,我们可以在管道操作中添加错误处理逻辑。这里使用了 requestfs 模块,但请注意这些模块已经不再维护。推荐使用更现代的替代方案,例如 node-fetchfs/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);
  }
});

关键点

  1. 错误处理:在 requestwriteStream 中都添加了错误处理。
  2. 文件路径:使用 path 模块来确保生成正确的文件路径。
  3. 资源管理:确保在流操作完成或出错时正确关闭资源。

通过这种方式,你可以更健壮地处理抓取图片过程中的各种错误情况。


我也碰上了。用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));
      });
    });
  }
});

上述代码做了以下改进:

  1. 添加了mkdirp的错误处理。
  2. request(imageUrl)上添加了错误处理,以便捕获下载图片时可能发生的错误。
  3. fs.createWriteStream上添加了错误处理,以捕获写入文件时可能出现的问题。

通过这些改进,可以更好地调试和定位错误,从而提高程序的健壮性。

回到顶部