分享一个自动爬取静态站的工具

分享一个自动爬取静态站的工具

点点

2021-03-28 20:47 阅读 244 喜欢 0

资源

抓取页面最主要的还是页面中涉及到的资源,将资源主要分为以下几个:

css文件 js文件 页面引入的图片 css引入的图片 页面做的背景图

规则

在抓取资源的时候也不是所有都抓取,有些网站引入的是cdn或者外部的资源文件,这类的就不准备抓取了,直接使用,还有些图片跟站点的域名不同,也需要将host添加进来,防止图片不再下载。

因此,做了以下几个变量:

//定义几个资源的前置路径,可以为空 //*** CSS 文件的路径前缀 let cssprefix = '/static/css/', //=== 图片文件的路径前缀 imgprefix = '/static/image/', //=== js文件的路径前缀 jsprefix = '/static/js/', //=== css文件中的使用的背景图片相对于css文件的相对路径. cssimgprefix = '../image/'; //抓取目标内容 let targetUrl = http://xxx.html, targetFolderName = 宝翔电商; let targetHost = ['www.xxx.com','hz.xxx.com']; let pageCode = 'utf8';//页面编码,默认utf8,有些页面是gbk. let deepFetch = false;//是否深度抓取,false则只抓取当前页面,true则从当前页面进行继续抓取。 let staticDomain = []; 定义好存储目录以及对应的host和编码,就可以开始了,给定一个入口路径,从该页面开始抓取A标签,进行挨个获取和存储。

核心代码

代码很简单,就是获取html代码后进行img css 内容解析就OK了,然后做个循环,依次抓取。

//流程: /**

//初始创建文件夹 if(!fs.existsSync(folderPath)){ fs.mkdirSync(folderPath); // fs.mkdirSync(path.join(folderPath,'css')) // fs.mkdirSync(path.join(folderPath,'js')) // fs.mkdirSync(path.join(folderPath,'img')) // fs.mkdirSync(path.join(folderPath,'bg')) }

; //做循环处理 var urlMap = {};//做去重处理。

(async function(){ while(pageUrlArr.length > 0){ //每次都是第一个 var currentUrl = pageUrlArr.splice(0,1)[0]; console.log(开始抓取页面:${currentUrl}) //对href进行甄别处理。 var fileNameObj = tool.getFileName(currentUrl); if(targetHost.indexOf(fileNameObj.host) > -1){//不是本站数据,忽略。 //获取html let htmlContent = await tool.fetch(currentUrl); //如果无法访问则忽略 if(htmlContent != ''){ //加入判断map let ccodeurl = encodeURIComponent(currentUrl); urlMap[ccodeurl] = fileNameObj.fileName;//加入map,防止重复下载 //对内容进行解析,获得地址信息。 let $ = cheerio.load(htmlContent); //检索所有的相关数据以及图片等 const $a = $('a');//所有的a标签,并进行记录判断 console.log(获得A标签:${$a.length}) $a.each(function(index,item){ var ahref = $(item).attr('href'); if(ahref && ahref.indexOf('javascript') < 0 && ahref.indexOf('void') < 0){//存在且不是js函数 // var ahrefobj = url.parse(ahref); let realHref = ahref; //如果不是hostname if(tool.shouldDown(ahrefobj)){//引入的其他的站点地址 if(ahrefobj.host == null){ realHref = new URL(ahref,currentUrl).href; } //并进行替换。 var fileInfo = tool.getFileName(realHref); //此处替换需要通过正则进行替换 let regexp = new RegExp('"('+ahref+')"','g'); htmlContent = htmlContent.replace(regexp,'"'+fileInfo.fileName+'"'); let acodeurl = encodeURIComponent(realHref); if(!urlMap[acodeurl] && deepFetch){ urlMap[acodeurl] = fileInfo.fileName; pageUrlArr.push(realHref); } } } })

            //js文件
            const $script = $('script').get();
            console.log(`获得js文件:${$script.length}`)
            for(let i in $script){
                let item = $script[i];
                let shref = $(item).attr('src');
                if(shref){
                    let shrefobj = url.parse(shref);
                    let realHref = shref;
                    if(tool.shouldDown(shrefobj)){//相对路径
                        //进行下载。
                        if(shrefobj.host == null){
                            realHref = new URL(shref,currentUrl).href;
                        }
                        let fileInfo = tool.getFileName(realHref);
                        htmlContent = htmlContent.replace(shref,jsprefix+fileInfo.fileName)
                        await tool.download(path.join(folderPath,jsprefix,fileInfo.fileName),realHref);
                    }
                }
            }

            //css文件
            const $css = $('link').get();
            console.log(`获得css文件:${$css.length}`)
            for(let i in $css){
                let item = $css[i];
                let chref = $(item).attr('href');
                if(chref){
                    let realHref = chref;
                    let chrefobj = url.parse(chref);
                    if(tool.shouldDown(chrefobj)){//相对路径
                        //进行下载。
                        if(chrefobj.host == null){
                            realHref = new URL(chref,currentUrl).href;
                        }
                        let fileInfo = tool.getFileName(realHref);
                        htmlContent = htmlContent.replace(chref,cssprefix+fileInfo.fileName)
                        let cssContent = '';
                        try{
                            cssContent = await tool.fetch(realHref);
                        }catch(e){
                            console.log(`抓取失败:${e.message},${realHref}`)
                        }
                        //对css内容进行处理。
                        let cssarr = cssContent.match(/url\(([\s\S^]*?)\)/g);
                        if(cssarr && cssarr.length > 0){//存在
                            for(let m in cssarr){
                                let cssitem = cssarr[m];
                                let tempPath = (cssitem.match(/url\(([\s\S^]*?)\)/)[1]).trim();
                                tempPath = tempPath.replace(/"/g,'');
                                let cssbgreal = new URL(tempPath,realHref).href;
                                //下载
                                let cssbgInfo = tool.getFileName(cssbgreal);
                                cssContent = cssContent.replace(tempPath,cssimgprefix+cssbgInfo.fileName);
                                await tool.download(path.join(folderPath,imgprefix,cssbgInfo.fileName),cssbgreal);
                            }
                        }
                        //吸入
                        let tempCssPath = path.join(folderPath,cssprefix,fileInfo.fileName);
                        tool.mkdir(path.dirname(tempCssPath))
                        fs.writeFileSync(tempCssPath,cssContent);
                    }
                }
            }

            //img 文件
            const $img = $('img').get();
            console.log(`获得图片:${$img.length}`)
            for(let i in $img){
                let item = $img[i];
                let chref = $(item).attr('src');
                //由于
                if(imgAttr!='' && $(item).attr(imgAttr) != undefined){
                    let dchref = $(item).attr(imgAttr);
                    let dchrefobj = url.parse(dchref);
                    let drealHref = dchref;
                    if(tool.shouldDown(dchrefobj)){//相对路径
                        //进行下载。
                        if(dchrefobj.host == null){
                            drealHref = new URL(dchref,currentUrl).href;
                        }
                        let dfileInfo = tool.getFileName(drealHref);
                        htmlContent = htmlContent.replace(dchref,imgprefix+dfileInfo.fileName);
                        await tool.download(path.join(folderPath,imgprefix,dfileInfo.fileName),drealHref);
                    }
                }
                if(chref){
                    let chrefobj = url.parse(chref);
                    let realHref = chref;
                    if(tool.shouldDown(chrefobj)){//相对路径
                        //进行下载。

                        if(chrefobj.host == null){
                            realHref = new URL(chref,currentUrl).href;
                        }
                        let fileInfo = tool.getFileName(realHref);
                        htmlContent = htmlContent.replace(chref,imgprefix+fileInfo.fileName);
                        await tool.download(path.join(folderPath,imgprefix,fileInfo.fileName),realHref);
                    }
                }
            }

            //处理最后的background-image 的写死样式问题
            let bgarr = htmlContent.match(/url\(([\s\S^]*?)\)/g);
            console.log(`处理css内引用文件`)
            if(bgarr && bgarr.length > 0){//存在
                for(let m in bgarr){
                    let bgitem = bgarr[m];
                    let tempPath = (bgitem.match(/url\(([\s\S^]*?)\)/)[1]).trim();
                    tempPath = tempPath.replace(/"/g,'');
                    let bgreal = new URL(tempPath,currentUrl).href;
                    //下载
                    let bgInfo = tool.getFileName(bgreal);
                    htmlContent = htmlContent.replace(tempPath,imgprefix+bgInfo.fileName);
                    await tool.download(path.join(folderPath,imgprefix,bgInfo.fileName),bgreal);
                }
            }

            //将html存储起来。
            let currentFilePath = path.join(folderPath,fileNameObj.fileName);
            tool.mkdir(path.dirname(currentFilePath));
            // htmlContent = htmlContent.replace(currentUrl,fileNameObj.fileName);
            fs.writeFileSync(currentFilePath,htmlContent);

        }
    }
}
console.log(`执行完毕----------------`)
process.exit(0);

})();

效果还不错与原网站一样,稍微改动下就换了个名。

转载请注明出处: http://sdxlp.cn/article/gongju.html


如果对你有用的话,请赏给作者一个馒头吧 ...或帮点下页面底部的广告,感谢!!

赞赏支持
提交评论
评论信息(请文明评论)
暂无评论,快来快来写想法...
推荐
做个nodejs的项目,使用了thinkjs 3.0 的框架,编辑器为vs code ,之前用的好好的,每次 . 后都有提示的,可是使用了多模块后发现.. model的提示没有了..vs code 可以加插件,于是准备做个简易的插件自用
小伙伴们在自驾出远门时,是不是有和我同款的路盲人士呀?基本远行都是不记路,开导航的,那我经常使用的就是高德了,高德有好多的语音,高德地图一条小团团语音包怎么设置?在最近,高德地图上线了一条小团团的导航语音包,很多人都想将自己的导航语音包设置为一条小团团的语音包,但是具体该怎么设置呢,怎么更换为一条小团团语音包,下面就和点点一起来看看吧!
通讯软件有很多,但我们常用的就是微信,微信中的游戏小程序是很多的,可是如果我们不玩的话,就可以选择关闭其入口,今天小编就告诉小伙伴们手机微信怎么关闭发现页中的游戏入口。
微信收款码是分为个人码和商家码两种,虽然看似差不多,但其实功能上是有差别的。商家收款码不仅支持顾客使用信用卡支付,还可以享受直接提现等便利功能。那么微信商家收款码怎么申请?第一步商户需要开通微信收款商业版。
我们日常必备的聊天工具微信,在使用的时候也有误删人的情况出现,这个时候小伙伴们知道怎么悄悄的将删除的人加回来呢?最快将删除的人加回来的方法有哪些呢?
日常生活中,我们经常使用到手机热点,它相当于一个移动路由器,可以开启WiFi在其他设备上直接连接使用,而且打开手机热点操作非常简单,那小伙伴们开启手机热点之后为什么连接不上呢,下面就和小编一起来看看吧!
如果你平时也不爱听六十秒的语音,或者是因为没带耳机,不方便听语音,那么不妨赶快跟着本文将语音自动转换成文字的方法设置起来,这样一来,不管是不爱听语音,还是不方便听语音,都能够轻松的知道别人想说的是什么了,令日常沟通变得更加便利。
​QQ9.0版本终于发布了!作为中国最大的社交软件之一,QQ一直备受关注。这次,QQ团队带来了全新的9.0版本,不仅在界面上进行了大刀阔斧的改革,还加入了许多实用的新功能。让我们一起来看看这次QQ9.0有哪些值得期待的亮点吧!