爬虫期末作业
基于第一个项目爬虫爬取的数据,完成数据展示网站。
一、基本要求
1.用户可注册登录网站,非注册用户不可登录查看数据
这里有几个分任务:
(1)前端建立登录和注册网页(运用html和css)
我学习了一波大神分享的网页设置,做了个动态毛玻璃样式的网页:
底下框起来的两行分别是 找回密码 和 注册账号,
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Glassmorphism Login Form</title>
<link rel="stylesheet" href="style.css">
<script type="text/javascript" src="login.js"></script>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>
<body>
<section>
<div class="color"></div>
<div class="color"></div>
<div class="color"></div>
<div class="box">
<div class="square" style="--i:0;"></div>
<div class="square" style="--i:1;"></div>
<div class="square" style="--i:2;"></div>
<div class="square" style="--i:3;"></div>
<div class="square" style="--i:4;"></div>
<div class="container">
<div class="form">
<h2>Login Form</h2>
<form>
<div class="inputBox">
<input id="uname" type="text" name="user" placeholder="Username">
</div>
<div class="inputBox">
<input id="upass" type="password" name="psw" placeholder="Password">
</div>
<div class="inputBox">
<input type="submit" value="Login">
</div>
<p class="forget">Forget password ? <a href="#">Click Here</a></p>
<p class="forget">Don't have an account ? <a href="sign.html">Sign up</a></p>
</form>
</div>
</div>
</div>
</section>
</body>
</html>
点击注册账号的话会转入注册界面👇
主要提供了输入用户名和密码部分的输入框以及一个注册按钮。
sign.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>注册界面</title>
<script type="text/javascript" src="login.js"></script>
<link rel="stylesheet" href="style.css">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>
<body>
<section>
<div class="color"></div>
<div class="color"></div>
<div class="color"></div>
<div class="box">
<div class="square" style="--i:0;"></div>
<div class="square" style="--i:1;"></div>
<div class="square" style="--i:2;"></div>
<div class="square" style="--i:3;"></div>
<div class="square" style="--i:4;"></div>
<div class="container">
<div class="form">
<h2>Signup Form</h2>
<form>
<div class="inputBox">
<input id="uname" type="text" name="user" placeholder="Create username">
</div>
<div class="inputBox">
<input id="upass" type="password" name="psw" placeholder="Password">
</div>
<div id="error_box"></div>
<div class="inputBox">
<input type="submit" value="Sign up" onclick="Regist()" class="btn btn-primary">
</div>
</form>
</div>
</div>
</div>
</section>
</body>
</html>
(css的具体代码实现放在文件夹里了)
(2)后端实现
/*
在点击注册按钮之后,会调用Regist函数,函数全部存储在login.js中。
会先检查用户名以及用户密码的长度,是否符合规范,如果不符合,则会进行提示,并且之间返回。
代码如下:
*/
var oUname = document.getElementById("uname");
var oUpass = document.getElementById("upass");
var oError = document.getElementById("error_box")
var isError = true;
console.log(oUname.value);
if (oUpass.value.length > 10 || oUpass.value.length < 3) {
oError.innerHTML = "密码请输入6-20位字符"
isError = false;
return;
}
if (oUname.value.length > 10 || oUname.value.length < 3) {
oError.innerHTML = "用户名请输入3-10位字符";
isError = false;
return;
}
/*
检查之后,将表单进行提交提交,代码如下:
*/
var params = '/process_regist';
$.post(params, {name: oUname.value,passwd: oUpass.value},function(text, status) {
console.log(text);
JSON.parse(text, function(k,v) {
if(v == true) {
window.alert("注册成功");
}else{
window.alert("已经注册过");
}
window.location.href = "login.html";
// location.reload();
})
})
相关js操作插入在html里:
<!-- <script src="../node_modules/angular/angular.min.js"></script>-->
<script src="/angular/angular.min.js"></script>
<!-- 引入自己的样式与js-->
<link rel="stylesheet" type="text/css" href="stylesheets/style.css">
<script type="text/javascript" src="javascripts/users.js"></script>
<script>
var app = angular.module('login', []);
app.controller('loginCtrl', function ($scope, $http, $timeout) {
// 登录时,检查用户输入的账户密码是否与数据库中的一致
$scope.check_pwd = function () {
var data = JSON.stringify({
username: $scope.username,
password: $scope.password
});
$http.post("/users/login", data)
.then(
function (res) {
if(res.data.msg=='ok') {
window.location.href='/news.html';
}else{
$scope.msg=res.data.msg;
}
},
function (err) {
$scope.msg = err.data;
});
};
//增加注册用户
$scope.doAdd = function () {
// 检查用户注册时,输入的两次密码是否一致
if($scope.add_password!==$scope.confirm_password){
// $timeout(function () {
// $scope.msg = '两次密码不一致!';
// },100);
$scope.msg = '两次密码不一致!';
}
else {
var data = JSON.stringify({
username: $scope.add_username,
password: $scope.add_password
});
$http.post("/users/register", data)
.then(function (res) {
if(res.data.msg=='成功注册!请登录') {
$scope.msg=res.data.msg;
$timeout(function () {
window.location.href='index.html';
},2000);
} else {
$scope.msg = res.data.msg;
}
}, function (err) {
$scope.msg = err.data;
});
}
};
});
</script>
之后会用users.js调用信息:
var express = require('express');
var router = express.Router();
var userDAO = require('../dao/userDAO');
router.post('/login', function(req, res) {
var username = req.body.username;
var password = req.body.password;
// var sess = req.session;
userDAO.getByUsername(username, function (user) {
if(user.length==0){
res.json({msg:'用户不存在!请检查后输入'});
}else {
if(password===user[0].password){
req.session['username'] = username;
res.cookie('username', username);
res.json({msg: 'ok'});
// res.json({msg:'ok'});
}else{
res.json({msg:'用户名或密码错误!请检查后输入'});
}
}
});
});
/* add users */
router.post('/register', function (req, res) {
var add_user = req.body;
// 先检查用户是否存在
userDAO.getByUsername(add_user.username, function (user) {
if (user.length != 0) {
// res.render('index', {msg:'用户不存在!'});
res.json({msg: '用户已存在!'});
}else {
userDAO.add(add_user, function (success) {
res.json({msg: '成功注册!请登录'});
})
}
});
});
// 退出登录
router.get('/logout', function(req, res, next){
// 备注:这里用的 session-file-store 在destroy 方法里,并没有销毁cookie
// 所以客户端的 cookie 还是存在,导致的问题 --> 退出登陆后,服务端检测到cookie
// 然后去查找对应的 session 文件,报错
// session-file-store 本身的bug
req.session.destroy(function(err) {
if(err){
res.json('退出登录失败');
return;
}
// req.session.loginUser = null;
res.clearCookie('username');
res.json({result:'/index.html'});
});
});
module.exports = router;
(注意要保存session信息,不然记录用户操作日志时,不知道是哪位用户进行的操作。示例的session信息只保存在启动网站内存中,所以网站重启后信息丢失;也可以新建数据库保存session信息。)【这里的session存在app.js里】
然后调用到userDAO.js:
var mysql = require('mysql');
var mysqlConf = require('../conf/mysqlConf');
var userSqlMap = require('./userSqlMap');
var pool = mysql.createPool(mysqlConf.mysql);
// 使用了连接池,重复使用数据库连接,而不必每执行一次CRUD操作就获取、释放一次数据库连接,从而提高了对数据库操作的性能。
module.exports = {
add: function (user, callback) {
pool.query(userSqlMap.add, [user.username, user.password], function (error, result) {
if (error) throw error;
callback(result.affectedRows > 0);
});
},
getByUsername: function (username, callback) {
pool.query(userSqlMap.getByUsername, [username], function (error, result) {
if (error) throw error;
callback(result);
});
},
};
2.用户注册、登录、查询等操作记入数据库中的日志
先在mysql里建两个表,分别用来存用户信息和日志信息,其中用户信息表中存储了用户名以及用户的密码,日志中存储了用户名、操作时间和具体操作。
3.爬虫数据查询结果列表支持分页和排序
这里用到了Bootstrap Table : https://www.bootstrap-table.com.cn/doc/getting-started/introduction/ 👈学习地址。
一定记得在代码最上面header里加上:
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<link rel="stylesheet" href="https://unpkg.com/bootstrap-table@1.15.3/dist/bootstrap-table.min.css">
在代码最下面script下方加上:
<script src="https://unpkg.com/bootstrap-table@1.15.3/dist/bootstrap-table.min.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
<script src="https://unpkg.com/bootstrap-table@1.15.3/dist/bootstrap-table.min.js"></script>
(除了在查询的时候进行排序,还可以通过bootstrap table 提供了一个前端排序的方法,用户能够通过指定列旁边的小箭头,来对该列值进行升序或降序排序)
$('#record2').bootstrapTable({
url:params,
method:'GET',
pagination:true,
sidePagination:'client',
pageSize:5,
striped : true,
sortable : true,
sortOrder:"asc",
showRefresh:true,
search:true,
showToggle: true,
toolbar: '#toolbar',
showColumns : true,
columns:[{
field :'url',
title : 'url',
sortable : true
}, {
field:'title',
title:'title'
}, {
field:'source_name',
title:'source_name',
sortable : true
},{
field:'author',
title:'author'
},{
field:'publish_date',
title:'publish_date',
sortable : true
}]
})
整体代码:
<form>
<!-- <marquee><font color="#8B008B">建议查询: 新闻/中国...</font></marquee> -->
<body background="2.jpg"
style=" background-repeat:no-repeat ;
background-size:100% 100%;
background-attachment: fixed;"
>
<br>
<select class="SearchOptions" name = "sort" id = "sortid" style ="float: left; ">
<option value="title">标题 (title)</option>
<option value="keywords">新闻来源 (author)</option>
<option value="publish_time">发布日期 (publish_date)</option>
<option value="source_name">内容 (content)</option>
</select>
<div class="container" style ="float: left; width: 100%;">
<form action="" class="parent">
<input type="text" class="search" name="title_text" placeholder="请输入查询关键字" style="border-radius: 8px; ">
<input type="button" class="form-submit" style = "float:left; " value="查询">
</form>
</div>
</form>
👆基础的表格结果展示
<script>
$(document).ready(function() {
$.get('/check', function(data) {
console.log(data);
if(data == false) {
window.alert("用户未登录");
window.location.href = "login.html";
}
});
$("input:button").click(function() {
var title = $("input:text").val();
var sort = $('#sortid').val();
console.log("title = " + title);
console.log("sort = " + sort);
var params = '/process_get?title=' + $("input:text").val() + '&sort=' + sort +'&order=asc';
$(function(){
console.log(params);
$("#record2").empty();
$('#record2').bootstrapTable({
url:params,
method:'GET',
pagination:true,
sidePagination:'client',
pageSize:5,
striped : true,
sortable : true,
sortOrder:"asc",
showRefresh:true,
search:true,
showToggle: true,
toolbar: '#toolbar',
showColumns : true,
columns:[{
field :'url',
title : 'url',
sortable : true
}, {
field:'title',
title:'title'
}, {
field:'source_name',
title:'source_name',
sortable : true
},{
field:'author',
title:'author'
},{
field:'publish_time',
title:'publish_time',
sortable : true
}]
})
});
});
});
</script>
👆通过js来以表格的形式显示数据
(通过GET方法访问给定的url,并且将返回的json文件,解析生成表格,注意下面field的值应该和返回的json文件对应属性的keyvalue相同。)
下面就是运行search.html后的结果:
查询总页面👆
这里可以选择要从哪里寻找查询关键字👆
这里可以分页查询👆
这里是鼠标移到相应新闻上会有加暗效果出现👆
这里可以选择查询表格里显示哪些表头👆
这里选择一页里包括多少条新闻行数👆
如果按下右上角那个Toggle,可以更改页面样式,由纵分割变成横分割👆
👆对 index.js 做的相应更改!!【这里一定记住要改,我一开始就是忘记了这块儿,一直显示不出来数据 /(ㄒoㄒ)/~~】
4.用Echarts或者D3实现3个以上的数据分析图表展示在网站中
这里我用ECharts来实现:下载地址 。
实现四个图的展示代码放在news.js里:
$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: pattern.exec(element["x"])[1], 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();
};
}
});
}
记住要在项目文件夹下cmd运行node bin/www,我第一次运行出了错误,用npm install xxx(你的报错)就解决了~
输入网址:http://127.0.0.1:3000/login.html,发现自己目前还没有账号,于是选择注册账号,转到注册页面:/sign.html。
注册成功之后会再次转回登陆界面,输入刚刚填写的名称和密码就可以进入查询主页了。
此时数据库会记录你的注册信息:
查询界面是search.html和news.html的结合
(因为news.html里引入了search.html):
(前面已经介绍过了search.html的实现效果)
这部分主要介绍转到news.html之后可以进行的操作,那就是选择四种不同的图表来表示出你的查询数据结果。
柱状图 :
饼状图 :
折线图 :
然后我就遇到了困难,那就是…nodejieba那个词云压根打不开…
这时助教正好在群里发了新的解决方法:
1、把wordcut.js文件替换成以下这个,这个换了一个分词器。
// 载入模块
// var nodejieba = require('nodejieba');
var Segmenter = require('node-analyzer');
//正则表达式去掉一些无用的字符,与高频但无意义的词。
const regex = /[\t\s\r\n\d\w]|[\+\-\(\),\.。,!?《》@、【】"'::%-\/“”]/g;
var wordcut = function(vals) {
var segmenter = new Segmenter();
var word_freq = {};
vals.forEach(function (content){
var newcontent = content["content"].replace(regex,'');
if(newcontent.length !== 0){
// console.log();
var words = segmenter.analyze(newcontent).split(' ');
// var words = nodejieba.cut(newcontent);
words.forEach(function (word){
word = word.toString();
word_freq[word] = (word_freq[word] +1 ) || 1;
});
};
});
return word_freq;
};
exports.wordcut = wordcut;
2、命令行输入npm install node-analyzer -save
3、freqchange.js中删掉 第2行 var nodejieba = require(‘nodejieba’);
再运行了一次就成功啦!
(顺便可以检验网站已注册账号的登录和查询情况)
词云 :
5.实现一个管理端界面,可以查看(查看用户的操作记录)和管理(停用启用)注册用户。
直接在app.js中,引入var logger = require('morgan’);
借助中间件保存的信息
// module.exports = app;
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var logger = require('morgan');
var logDAO = require('./dao/logDAO.js');
// var fs = require('fs');//加了文件操作的模块
// var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flag: 'a' });//创建一个写文件流,并且保存在当前文件夹的access.log文件中
// var indexRouter = require('./routes/users');
var usersRouter = require('./routes/users');
var newsRouter = require('./routes/news');
var app = express();
//设置session
app.use(session({
secret: 'sessiontest',//与cookieParser中的一致
resave: true,
saveUninitialized: false, // 是否保存未初始化的会话
cookie : {
maxAge : 1000 * 60 * 60, // 设置 session 的有效时间,单位毫秒
},
}));
// view engine setup
// app.set('views', path.join(__dirname, 'views'));
// app.set('view engine', 'ejs');
let method = '';
app.use(logger(function (tokens, req, res) {
console.log('打印的日志信息:');
var request_time = new Date();
var request_method = tokens.method(req, res);
var request_url = tokens.url(req, res);
var status = tokens.status(req, res);
var remote_addr = tokens['remote-addr'](req, res);
if(req.session){
var username = req.session['username']||'notlogin';
}else {
var username = 'notlogin';
}
// 直接将用户操作记入mysql中
if(username!='notlogin'){
logDAO.userlog([username,request_time,request_method,request_url,status,remote_addr], function (success) {
console.log('成功保存!');
})
}
console.log('请求时间 = ', request_time);
console.log('请求方式 = ', request_method);
console.log('请求链接 = ', request_url);
console.log('请求状态 = ', status);
console.log('请求长度 = ', tokens.res(req, res, 'content-length'),);
console.log('响应时间 = ', tokens['response-time'](req, res) + 'ms');
console.log('远程地址 = ', remote_addr);
console.log('远程用户 = ', tokens['remote-user'](req, res));
console.log('http版本 = ', tokens['http-version'](req, res));
console.log('浏览器信息 = ', tokens['user-agent'](req, res));
console.log('用户 = ', username);
console.log(' ===============',method);
}, ));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/angular', express.static(path.join(__dirname , '/node_modules/angular')));
// app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/news', newsRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
// res.render('error');
});
module.exports = app;
查看用户注册信息:
查看用户操作信息:
二、拓展要求
(因为时间和能力有限,这里先说一下自己的想法好了,日后有机会再回来完善⁽⁽꜀(:3꜂ ꜆)꜄⁾⁾)
1.实现对爬虫数据中文分词的查询
因为不太理解这项任务的具体意思,所以去询问了一下老师,老师说就是对爬虫爬取的文本做中文分词后再做查询,有一些语义不同的查询结果就可以抛弃了,比如“南京市长江大桥”分词结果是“南京市/长江/大桥”,这种情况下查询“市长”就查不到了,而不做分词的时候按照like查询“市长”是可以查到这个语料的。
2.实现查询结果按照主题词打分的排序
估计是按照keyword进行一些相关操作(੭ ᐕ)੭
3.用Elastic Search+Kibana展示爬虫的数据结果
这里可以参考这个博客:干货:Kibana 可视化ElasticSearch数据展示分析
总结
感谢:
https://blog.csdn.net/yc_hong/article/details/105886576
这位大佬的博客!和老师、助教们的帮助与指导,至此web编程课圆满结束!(撒花★,°:.☆( ̄▽ ̄)/$:.°★ 。)