爬虫数据查询

这东西对我大一新生而言真是太不友善了555...弄了好久、头晕眼花,研究这老师的代码,对着一个个改成自己数据库对应的东西,总算是把数据查询所涉及的这些东西都大致搞完搞明白了...吧?下面就来聊聊我这几天到处找人帮忙、问问题终于整出来的成果...

基于第一个项目爬虫爬取的数据,要让用户可注册登录网站,非注册用户不可登录查看数据。具体的代码很多,就不放在这儿了。做出来的登录页面如图所示:

第一次登录要先注册,注册成功后回到登录页面,若输入密码与用户名不匹配,则会有以下显示:

注册这里的代码有好多,说实话,我也没太懂,只知大概...连上了就行叭!

进入成功后,搜索页面是长这样的。这是对爬虫数据查询结果列表的呈现,可以通过搜关键字查找想要的新闻。

如想找内容里带“三分”字眼的欣慰,就在搜索框内输入“三分”,点查询查找。

表格呈现的前端代码比较简单在这里就不搬运了。实现该服务的后端代码为:

        var sql = 'select * from news ';

        if(searchparam["t2"]!="undefined"){
            sql +=(`where Title like '%${searchparam["t1"]}%' ${searchparam['ts']} Title like '%${searchparam["t2"]}%' `);
        }else if(searchparam["t1"]!="undefined"){
            sql +=(`where Title like '%${searchparam["t1"]}%' `);
        };

        if(searchparam["t1"]=="undefined"&&searchparam["t2"]=="undefined"&&searchparam["c1"]!="undefined"){
            sql+='where ';
        }else if(searchparam["t1"]!="undefined"&&searchparam["c1"]!="undefined"){
            sql+='and ';
        }

        if(searchparam["c2"]!="undefined"){
            sql +=(`Content like '%${searchparam["c1"]}%' ${searchparam['cs']} Content like '%${searchparam["c2"]}%' `);
        }else if(searchparam["c1"]!="undefined"){
            sql +=(`Content like '%${searchparam["c1"]}%' `);
        }

        if(searchparam['stime']!="undefined"){
            if(searchparam['stime']=="1"){
                sql+='ORDER BY Time ASC ';
            }else {
                sql+='ORDER BY Time DESC ';
            }
        }

代码段意思:从数据库news里查找关键词,若标题、内容有输入的关键词则输出相应新闻;最后一段的意思为按时间顺序呈现所找到的新闻。

数据分析图的展现就更花里胡哨了(bushi),图片页面就比较多了,但基本上是一个意思,都是要把新闻的一些属性抓取出来进行对比呈现。

比如,第一个是新闻发布数随时间变化的条形图,是对新闻发布时间Time的分析呈现。由于我之前找的是连续几天的NBA篮球赛事新闻,所以每天新闻发布数差不多。图长这样:

而决定图形状的关键句——从news中抓出时间并按时间顺序呈现如下:

只从news数据库里抓取新闻时间,后进行归纳生成条形图。
下面的饼图是对新闻来源数量的对比呈现:

与上一个意思大致相同,只是它的分类依据变成了新闻来源,从news数据库里抓取新闻来源,后进行归纳生成饼图。

再来是某个关键词的出现频率随时间变化图(我的电脑可能有bug,抓不全...换了好几个关键词都只能抓到这个程度,我也很无奈啊,凑合着看看...):

这个稍微有点不同的是抓取的关键词是写代码的时候就固定的,搜索news里新闻内容带有关键词——也就是“三分”的内容和时间做参考变量,并最后以时间顺序呈现。

最后是词云(个人觉得没有背景的时候看着更好看),在从新闻内容里找高频词,出现频率越高的词明显能看出字体越大:

搜索高频词:

下面是四个图的操作代码:

$scope.histogram = function () {
        $scope.isShow = false;
        $http.get("/news/histogram")
            .then(
                function (res) {

                    if(res.data.message=='url'){
                        window.location.href=res.data.result;
                    }else {

                        // var newdata = washdata(data);
                        let xdata = [], ydata = [], newdata;

                        var pattern = /\d{4}-(\d{2}-\d{2})/;

                        res.data.result.forEach(function (element) {
                            // "x":"2020-04-28T16:00:00.000Z" ,对x进行处理,只取 月日
                            xdata.push(pattern.exec(element["x"])[1]);
                            ydata.push(element["y"]);
                        });
                        newdata = {"xdata": xdata, "ydata": ydata};

                        var myChart = echarts.init(document.getElementById('main1'));

                        // 指定图表的配置项和数据
                        var option = {
                            title: {
                                text: '新闻发布数随时间变化'
                            },
                            tooltip: {},
                            legend: {
                                data: ['新闻发布数']
                            },
                            xAxis: {
                                data: newdata["xdata"]
                            },

                            yAxis: {},
                            series: [{
                                name: '新闻数目',
                                type: 'bar',
                                data: newdata["ydata"]
                            }]
                        };
                        // 使用刚指定的配置项和数据显示图表。
                        myChart.setOption(option);
                    }
                },
                function (err) {
                    $scope.msg = err.data;
                });

    };
    $scope.pie = function () {
        $scope.isShow = false;
        $http.get("/news/pie").then(
            function (res) {
                if(res.data.message=='url'){
                    window.location.href=res.data.result;
                }else {
                    let newdata = [];

                    var pattern = /责任编辑:(.+)/;//匹配名字
                    res.data.result.forEach(function (element) {
                        // "x":  责任编辑:李夏君 ,对x进行处理,只取 名字
                        newdata.push({name: element["x"], value: element["y"]});

                    });

                    var myChart = echarts.init(document.getElementById('main1'));
                    var app = {};
                    option = null;
                    // 指定图表的配置项和数据
                    var option = {
                        title: {
                            text: '新闻来源数量',
                            x: 'center'
                        },
                        tooltip: {
                            trigger: 'item',
                            formatter: "{a} <br/>{b} : {c} ({d}%)"
                        },
                        legend: {
                            orient: 'vertical',
                            left: 'left',
                            // data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎']
                        },
                        series: [
                            {
                                name: '访问来源',
                                type: 'pie',
                                radius: '55%',
                                center: ['50%', '60%'],
                                data: newdata,
                                itemStyle: {
                                    emphasis: {
                                        shadowBlur: 10,
                                        shadowOffsetX: 0,
                                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                                    }
                                }
                            }
                        ]
                    };
                    // myChart.setOption(option);
                    app.currentIndex = -1;

                    setInterval(function () {
                        var dataLen = option.series[0].data.length;
                        // 取消之前高亮的图形
                        myChart.dispatchAction({
                            type: 'downplay',
                            seriesIndex: 0,
                            dataIndex: app.currentIndex
                        });
                        app.currentIndex = (app.currentIndex + 1) % dataLen;
                        // 高亮当前图形
                        myChart.dispatchAction({
                            type: 'highlight',
                            seriesIndex: 0,
                            dataIndex: app.currentIndex
                        });
                        // 显示 tooltip
                        myChart.dispatchAction({
                            type: 'showTip',
                            seriesIndex: 0,
                            dataIndex: app.currentIndex
                        });
                    }, 1000);
                    if (option && typeof option === "object") {
                        myChart.setOption(option, true);
                    }
                    ;
                }
            });
    };
    $scope.line = function () {
        $scope.isShow = false;
        $http.get("/news/line").then(
            function (res) {
                if(res.data.message=='url'){
                    window.location.href=res.data.result;
                }else {
                    var myChart = echarts.init(document.getElementById("main1"));
                    option = {
                        title: {
                            text: '"三分"该词在新闻中的出现次数随时间变化图'
                        },
                        xAxis: {
                            type: 'category',
                            data: Object.keys(res.data.result)
                        },
                        yAxis: {
                            type: 'value'
                        },
                        series: [{
                            data: Object.values(res.data.result),
                            type: 'line',
                            itemStyle: {normal: {label: {show: true}}}
                        }],

                    };

                    if (option && typeof option === "object") {
                        myChart.setOption(option, true);
                    }
                }

            });
    };
    $scope.wordcloud = function () {
        $scope.isShow = false;
        $http.get("/news/wordcloud").then(
            function (res) {
                if(res.data.message=='url'){
                    window.location.href=res.data.result;
                }else {
                    var mainContainer = document.getElementById('main1');

                    var chart = echarts.init(mainContainer);

                    var data = [];
                    for (var name in res.data.result) {
                        data.push({
                            name: name,
                            value: Math.sqrt(res.data.result[name])
                        })
                    }

                    var maskImage = new Image();
                    maskImage.src = './images/logo.png';

                    var option = {
                        title: {
                            text: '所有新闻内容 jieba分词 的词云展示'
                        },
                        series: [{
                            type: 'wordCloud',
                            sizeRange: [12, 60],
                            rotationRange: [-90, 90],
                            rotationStep: 45,
                            gridSize: 2,
                            shape: 'circle',
                            maskImage: maskImage,
                            drawOutOfBound: false,
                            textStyle: {
                                normal: {
                                    fontFamily: 'sans-serif',
                                    fontWeight: 'bold',
                                    // Color can be a callback function or a color string
                                    color: function () {
                                        // Random color
                                        return 'rgb(' + [
                                            Math.round(Math.random() * 160),
                                            Math.round(Math.random() * 160),
                                            Math.round(Math.random() * 160)
                                        ].join(',') + ')';
                                    }
                                },
                                emphasis: {
                                    shadowBlur: 10,
                                    shadowColor: '#333'
                                }
                            },
                            data: data
                        }]
                    };

                    maskImage.onload = function () {
                        // option.series[0].data = data;
                        chart.clear();
                        chart.setOption(option);
                    };

                    window.onresize = function () {
                        chart.resize();
                    };
                }

            });

最后是一个管理端,实现后查询用户的操作记录和管理(停用启用)注册用户的页面长这样:

呈现该页面的前端代码就不在这里赘述了。而在此之前要注册一个管理员账号,我使他为root,在我的数据库里将他的ID改为0,则他成为管理员。

root成为管理员后,用该账号登录,即可完成查看和管理注册用户的目的。比如在用户表中的用户1右边的框框内勾选停用,回到数据库便会发现他的state变成了0,即该用户处于被停用状态。若再用该账号登录则会显示“用户不存在或已被停用”,无法用该账号登录查看数据,只能通过管理员修改使用资格。

实现管理端界面部分代码如下:

router.get('/administrate',function(req,res,next){
  res.writeHead(200, { 'Content-Type': 'text/html; charset= utf-8' });
  
  let $=cheerio.load(fs.readFileSync("./public/administrate.html"));

  if(admitted.id!=0)
  {
    res.end('<script>alert("没有权限!");location.replace("/");</script>');
    return;
  }
  database.query_noparam('SELECT * FROM user;', function (qerr, vals, fields) {
    if (qerr) {
      console.error(qerr);
      res.end(`<script>alert("Database Error!");</script>`);
      return;
    }
    for (let i in vals) {
      $('table#usertable').append(`<tr class="item-usertable" dbid=${i}>
      <td>${vals[i].id}</td>
      <td>${vals[i].username}</td>
      <td><a href="/users/changeState?id=${vals[i].id}&state=${1 - vals[i].state}"><button>${vals[i].state == 0 ? "启用" : "停用"}</button></a></td>
    </tr>`);
    }
    database.query_noparam('SELECT * FROM user_action;', function (qerr1, vals1, fields1){
      if (qerr1) {
        console.error(qerr1);
        return;
      }
      for (let i in vals1) {
        $('table#user_action').append(`<tr class="item-userlog" dbid=${i}>
      <td>${vals1[i].id}</td>
      <td>${vals1[i].username}</td>
      <td>${vals1[i].request_method}</td>
      <td>${vals1[i].request_url}</td>
    </tr>`);
      }
      res.end($.html());
    });
  });
});


router.get('/changeState', function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  let userID = parseInt(req.query.id);
  let nextState = parseInt(req.query.state);
  if (admitted.id != 0) {
    res.end('<script>alert("没有权限!");location.replace("/users");</script>');
    return;
  }
  database.query('UPDATE user SET state = ? WHERE id = ?;', [nextState, userID], function(qerr, vals, fields) {
    if (qerr) {
      console.error(qerr);
      return;
    }
    res.end('<script>alert("改变用户状态成功!");location.replace("/users/administrate");</script>');
  });
});

module.exports = router;

总之,数据呈现网站内容、时间、来源什么的都要和自己的数据库对应上才能显示得出来。而且登录注册用户的信息最后也会生成表格存入你的数据库里,应该说数据显示网站和数据库是相连的。

大作业真的好难,但是弄好了之后还是很感动的(把自己感动了),收获感满满。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值