Nodejs JSDOM 自动下载其他网站的图片

Nodejs JSDOM 自动下载其他网站的图片

var jsdom = require(“jsdom”); var http = require(“http”); var fs = require(“fs”);

function catchCore(){ jsdom.env( “http://www.qiushibaike.com/hot/”, [“http://code.jquery.com/jquery.js”], function (errors, window) { if(errors){ console.log(errors); } var $ = window.$; // console.log($(“body”).html()); console.log($(“img”).length);

        $("img").each(function(idx,obj){
            var src = obj.src;
            if(/pic.qiushibaike.com/.test(src)){
           http.get(src, function(res) {
                res.setEncoding('binary');//二进制(binary)
                var imageData ='';
                res.on('data',function(data){//图片加载到内存变量
                    imageData += data;
                }).on('end',function(){//加载完毕保存图片
                    var imageName = src.substr(src.length-8,8);
                    fs.writeFile('public/images/'+imageName, imageData, 'binary', function (err) {//以二进制格式保存
                        if (err) throw err;
                        console.log('file saved');
                    });
                });

            }).on('error', function(e) {
                console.log("Got error: " + e.message);
            });
        }
    });

}

);

}

exports.start = catchCore;


3 回复

Nodejs JSDOM 自动下载其他网站的图片

在这个帖子中,我们将讨论如何使用 Node.js 和 JSDOM 库自动从其他网站下载图片。我们将以糗事百科为例,演示如何抓取网页中的图片并将其保存到本地。

依赖库

首先,我们需要安装一些必要的库:

npm install jsdom
npm install request

示例代码

const jsdom = require("jsdom");
const request = require("request");
const fs = require("fs");

function catchCore() {
    jsdom.env({
        url: "http://www.qiushibaike.com/hot/",
        scripts: ["https://code.jquery.com/jquery.min.js"],
        done: function (err, window) {
            if (err) {
                console.error(err);
                return;
            }

            const $ = window.$;

            // 获取所有的图片元素
            $("img").each((idx, obj) => {
                const src = obj.src;

                // 过滤出特定来源的图片
                if (/pic\.qiushibaike\.com/.test(src)) {
                    request(src).pipe(fs.createWriteStream(`public/images/${src.split('/').pop()}`))
                        .on('close', () => console.log(`File saved: ${src}`))
                        .on('error', (e) => console.error(`Error downloading image: ${src} - ${e.message}`));
                }
            });
        }
    });
}

exports.start = catchCore;

代码解析

  1. 引入依赖库

    const jsdom = require("jsdom");
    const request = require("request");
    const fs = require("fs");
    
  2. 定义 catchCore 函数

    function catchCore() {
    
  3. 使用 JSDOM 抓取网页内容

    jsdom.env({
        url: "http://www.qiushibaike.com/hot/",
        scripts: ["https://code.jquery.com/jquery.min.js"],
        done: function (err, window) {
    
  4. 处理错误

    if (err) {
        console.error(err);
        return;
    }
    
  5. 使用 jQuery 选择器获取所有图片元素

    const $ = window.$;
    $("img").each((idx, obj) => {
    
  6. 过滤出特定来源的图片

    const src = obj.src;
    if (/pic\.qiushibaike\.com/.test(src)) {
    
  7. 使用 request 库下载图片并保存到本地

    request(src).pipe(fs.createWriteStream(`public/images/${src.split('/').pop()}`))
        .on('close', () => console.log(`File saved: ${src}`))
        .on('error', (e) => console.error(`Error downloading image: ${src} - ${e.message}`));
    

通过上述步骤,我们可以抓取指定网站上的图片,并将它们保存到本地文件系统中。这个示例使用了 request 库来简化 HTTP 请求,而不仅仅是使用原生的 http 模块。这样可以使得代码更加简洁易读。


人生苦短,

  1. 为何不用 cheerio
  2. 为何不用 request

这段代码使用了jsdom来解析网页,并通过http模块来下载特定网站上的图片。以下是对该代码的解释及一些优化建议:

  1. 引入模块

    var jsdom = require("jsdom");
    var http = require("http");
    var fs = require("fs");
    
  2. 定义抓取核心函数

    function catchCore() {
        jsdom.env(
            "http://www.qiushibaike.com/hot/",
            ["http://code.jquery.com/jquery.js"],
            function (errors, window) {
                if (errors) {
                    console.log(errors);
                }
                var $ = window.$;
    
                // 获取所有图片元素
                $("img").each(function (idx, obj) {
                    var src = obj.src;
                    // 检查是否为特定来源的图片
                    if (/pic\.qiushibaike\.com/.test(src)) {
    
                        // 发起HTTP GET请求下载图片
                        http.get(src, function (res) {
                            res.setEncoding('binary'); // 设置响应编码为二进制
                            let imageData = '';
                            res.on('data', function (chunk) { // 将数据片段拼接成完整图片
                                imageData += chunk;
                            }).on('end', function () { // 当所有数据接收完毕后
                                let imageName = src.substring(src.lastIndexOf('/') + 1); // 提取文件名
                                fs.writeFile('public/images/' + imageName, imageData, 'binary', function (err) { // 将图片写入文件
                                    if (err) throw err;
                                    console.log('File saved');
                                });
                            });
    
                        }).on('error', function (e) {
                            console.log("Got error: " + e.message);
                        });
                    }
                });
            }
        );
    }
    
  3. 导出函数以便外部调用

    exports.start = catchCore;
    

代码说明

  • jsdom.env 用于在 Node.js 中创建一个虚拟的浏览器环境,从而可以像在浏览器中一样操作 DOM。
  • 使用 jQuery $ 来选择和遍历图片元素。
  • http.get 用于发起 HTTP GET 请求下载图片内容。
  • fs.writeFile 用于将图片内容保存到本地文件系统。

注意事项

  • 确保目标网站允许爬虫抓取。
  • 考虑使用更强大的库如 axiosnode-fetch 替代 http 模块。
  • 对于复杂的错误处理和图片文件名生成逻辑,建议进一步优化。
回到顶部