少年,想不想自制一个可制定规则的爬虫系统呀

已收录   阅读次数: 1,076
2022-11-1907:47:01 发表评论
摘要

这个可以定制规则的爬虫系统,隶属于伯衡君正在制作的财富增值攻略系统,整个系统尚未完成,但是这个信息聚合的爬虫系统基本完成了,可以公开一些核心代码,能够给一些需要的人启发来自制。本站之前也分享了不少相关爬虫内容,具体可以参看下方的前情提要,也受到了很多启发,详情内容,请看本篇文章……

分享至:
少年,想不想自制一个可制定规则的爬虫系统呀

开篇寄语

这个可以定制规则的爬虫系统,隶属于伯衡君正在制作的财富增值攻略系统,整个系统尚未完成,但是这个信息聚合的爬虫系统基本完成了,可以公开一些核心代码,能够给一些需要的人启发来自制。本站之前也分享了不少相关爬虫内容,具体可以参看下方的前情提要,也受到了很多启发,详情内容,请看本篇文章。

前情提要

包含技术

  • HTML + CSS + JavaScript + Node.js + Mysql
  • 其中,Node.js 需要使用的依赖包括:async、request、cheerio、utf8、mysql、iconv-lite(这个主要是解决非 utf-8 格式的网站爬取乱码问题)

内容详情

这个信息爬虫,伯衡君主要是用来辅助进行全球投资的,而伯衡君设计的财富增值攻略系统的宗旨——赚更多钱,花更少钱,从而达成财富最大程度增值,这里面的信息作用非常重要。

有效的信息可以帮助你更加科学投资,从而提高投资胜率,而花更少的钱则是需要信息带给你各种优惠信息,所以可见有效信息在个人财富增值上的妙用。

先来简单介绍一下这个爬虫系统的主要功能:

少年,想不想自制一个可制定规则的爬虫系统呀

目前,伯衡君将我感兴趣的新闻内容,按照类别分成了综合、财经、科技、观点、娱乐、影音、福利、学习和各国政府公告,而喜爱则是勾选感兴趣的文章后添加到的地方,类似于稍后即可。

如何想看某篇文章,可以点开后,直接前往对应具体网页查看详情。

而其中的黑名单,主要是屏蔽一些不感兴趣含有某些关键词的文章,如下所示:

少年,想不想自制一个可制定规则的爬虫系统呀

而爬取规则,则主要是受到一款漫画应用的影响,在前情提要中有写,名字叫做 Yealico,它就是通过对一些网站制定爬取规则,可以观看漫画和视频,有兴趣的朋友可以下载试试。

爬虫规则设置页面详情如下:

少年,想不想自制一个可制定规则的爬虫系统呀

有的信息源是采用的 Api 模式,有的是直接通过网站 DOM 爬取,有的则是通过 RSS 形式,因为 RSS 形式,伯衡君可以通过 inoreader 应用订阅获取,所以就没有编列规则在内。

有关 inoreader 相关内容,可以参看以下文章:

在爬虫获取的过程中,某些网站可能失效了,需要检测它的有效性,这个要注意,而有的网站没有失效,有可能因为改版,制定的规则失效了,所以也需要列出来爬取的内容条数,如果爬取条数显示是 0 的话,那就说明该网站改版了,需要从新制定规则。

规则模式一、二、三、四和五,是应对爬取内容的标题和内容所表现出来的差异而设计的,api 模式返回内容各不相同,这个需要单独对应,而四是指 <a></a> 标签中链接不带 https 这样开头的,而五则是 <a></a> 标签中链接带 https 这样开头的。

核心代码如下:

//提供寰宇新闻专区新闻采集信息
app.get('/api/globalNewsData', (req, res) => {
    var selectArr = [];//最新新闻集合
    var requests = [];
    var blackLists = [];//黑名单集合
    var favorLists = [];//收藏新闻集合
    var totalsLists = {};//爬取数量集合
    con.query(`SELECT * FROM editRulesTable WHERE action = 1 AND catalogue = ${req.query.catalogue}; SELECT * FROM blackListWords WHERE id = 1; SELECT * FROM globalNewsTable ORDER BY stars;`, function (err, result, fields) {
        let resLength = result[0].length;
        let newsLength = result[2].length;
        for (let i = 0; i < resLength; i++) {
            requests.push({
                url: result[0][i].rulesname,
                method: 'GET',
                headers: {
                    'Content-Type': 'text/html; charset=UTF-8',
                    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36'
                }
            });
        }
        masync.map(requests,function (obj, callback) {
            request(obj, function (error, response, body) {
                if (!error && response.statusCode == 200) {
                    try{
                        if (body.trim()[0] == '<') {
                            body = body
                        } else {
                            body = JSON.parse(body);
                        }
                    }catch(err){
                        console.info(obj.url);
                    }
                    con.query(`UPDATE editRulesTable SET valid = 0 WHERE rulesname = '${obj.url}'`, function (err, result, fields) {});
                    callback(null, body);
                } else {
                    con.query(`UPDATE editRulesTable SET valid = 1, action = 0 WHERE rulesname = '${obj.url}'`, function (err, result, fields) {});
                    callback(error || response.statusCode);
                }
            });
        }, function (err, results) {
            if (err) {
                console.log(err)
            } else {
                for (var i = 0; i < results.length; i++) {
                    if (result[0][i].classmodel == 3) {
                        try{
                            for (let a of results[i].data.cards[0].card_group) {
                                selectArr.push({ title: `【${result[0][i].webname}】${a.desc.trim()}`, url: `${a.scheme}` })
                            }
                        }catch(errors){
                            selectArr.push({ title: "【微博 api 出现问题,请检查地址以及配置规则】", url: "#" })
                        }
                    } else if (result[0][i].classmodel == 1) {
                        try{
                            for (let a of results[i].data) {
                                selectArr.push({ title: `【${result[0][i].webname}】${a.target.title.trim()}`, url: `${`https://www.zhihu.com/question/` + a.target.id}` })
                            }
                        }catch(errors){
                            selectArr.push({ title: "【知乎 api 出现问题,请检查地址以及配置规则】", url: "#" })
                        }
                    } else if (result[0][i].classmodel == 2) {
                        try{                        
                            for (let a of results[i].data.list) {
                                selectArr.push({ title: `【${result[0][i].webname}】${a.title.trim()}`, url: `${a.url}` })
                            }
                        }catch(errors){
                            selectArr.push({ title: "【腾讯新闻 api 出现问题,请检查地址以及配置规则】", url: "#" })
                        }
                    } else if (result[0][i].classmodel == 4) {
                        const $ = cheerio.load(results[i]);
                        let splitArr = result[0][i].content.split(',');
                        for (let j = 0; j < splitArr.length; j++) {
                            $(`${splitArr[j]}`).each(function () {
                                if (result[0][i].rulesname == 'https://www.yicai.com/') {
                                    try{
                                        let keys = `${$(this).find('h2').text().match(/[\u4e00-\u9fa5]/gi) == null ? $(this).find('h2').text() : $(this).find('h2').text().trim()}`;
                                        selectArr.push({ title: `【${result[0][i].webname}】` + keys, url: 'https://www.yicai.com' + `${$(this).attr('href')}` });
                                    }catch(errors){
                                        selectArr.push({ title: `【${result[0][i].webname} 出现问题,请检查地址以及配置规则】`, url: "#" });
                                    }
                                } else if (result[0][i].rulesname == 'https://business.sohu.com/') {
                                    try{
                                        let keys = `${$(this).text().match(/[\u4e00-\u9fa5]/gi) == null ? $(this).text() : $(this).text().trim()}`;
                                        selectArr.push({ title: `【${result[0][i].webname}】` + keys, url: $(this).attr('href').indexOf('https') > -1 ? `${$(this).attr('href')}` : `https://www.sohu.com${$(this).attr('href')}` });
                                    }catch(errors){
                                        selectArr.push({ title: `【${result[0][i].webname} 出现问题,请检查地址以及配置规则】`, url: "#" });
                                    }
                                }else if(result[0][i].rulesname == 'https://369369.xyz/host/'){
                                    try{
                                        let keys = `${$(this).text().match(/[\u4e00-\u9fa5]/gi) == null ? $(this).text() : $(this).text().trim()}`;
                                        selectArr.push({ title: `【${result[0][i].webname}】` + keys, url: `https://369369.xyz/host/${$(this).attr('href')}`});
                                    }catch(errors){
                                        selectArr.push({ title: `【${result[0][i].webname} 出现问题,请检查地址以及配置规则】`, url: "#" });
                                    }
                                }else {
                                    try{
                                        let paramName = `${$(this).attr('href')}`.indexOf('/') == 0 ? `${$(this).attr('href')}` : `/${$(this).attr('href')}`;
                                        let keys = `${$(this).text().match(/[\u4e00-\u9fa5]/gi) == null ? $(this).text() : $(this).text().trim()}`;
                                        selectArr.push({ title: `【${result[0][i].webname}】` + keys, url: new URL(result[0][i].rulesname).origin + paramName });
                                    }catch(errors){
                                        selectArr.push({ title: `【${result[0][i].webname} 出现问题,请检查地址以及配置规则】`, url: "#" });
                                    }
                                }
                            });
                        }
                    } else if (result[0][i].classmodel == 5) {
                        const $ = cheerio.load(results[i]);
                        let splitArr = result[0][i].content.split(',');
                        for (let j = 0; j < splitArr.length; j++) {
                            try{
                                $(`${splitArr[j]}`).each(function () {
                                    selectArr.push({ title: `【${result[0][i].webname}】` + `${$(this).text().match(/[\u4e00-\u9fa5]/gi) == null ? $(this).text() : $(this).text().trim() }`, url: `${$(this).attr('href')}` })
                                });
                            }catch(errors){
                                selectArr.push({ title: `【${result[0][i].webname} 出现问题,请检查地址以及配置规则】`, url: "#" });
                            }
                        }
                    }
                }
            }
            [...selectArr].map(x=>x.title.split('】')[0].slice(1)).forEach(function (x) { totalsLists[x] = (totalsLists[x] || 0) + 1; });
            let crawlTotalsKeys = Object.keys(totalsLists);
            let crawlTotalsVals = Object.values(totalsLists);
            for(let t = 0; t<crawlTotalsKeys.length; t++){
                con.query(`UPDATE editRulesTable SET totals = ${crawlTotalsVals[t]} WHERE webname = '${crawlTotalsKeys[t]}'`, function (err, result, fields) {});
            }
            const regex = new RegExp(`${result[1][0].title}`, 'g');
            selectArr = selectArr.sort((x, y) => x.title.length - y.title.length).filter(x => x.title.indexOf(`${req.query.yesfilter}`) > -1).filter((item, y) => !item.title.match(regex));
            selectArr = selectArr.filter(function (value, index) { return selectArr.map(x => x.title).indexOf(value.title) == index });
            //筛选出在收藏中文章
            for (let i = 0; i < newsLength; i++) {
                favorLists.push(result[2][i].title);
            }
            selectArr = selectArr.filter(x => favorLists.indexOf(x.title) == -1 && x.title.length >= 1);
            res.end(JSON.stringify([{ 'ret': true, 'code': selectArr }]), 'utf-8');
        });
    });
});

不是很难,感兴趣的朋友可以依此自行自制,依靠有效的信息,可以提高投资的胜率,同时,也能通过及时的信息,节省开支。

  • 我的微信
  • 微信扫一扫加好友
  • weinxin
  • 我的微信公众号
  • 扫描关注公众号
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: