文章目录
代码仓库:github
最好对着源码看此教程。
〇、功能设计
设置数据检索、指标分析、数据管理模块,数据检索提供给用户使用,后两个模块提供给管理员使用。此外还实现了权限拦截功能。
一、SpringBoot项目搭建
- 依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.13</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.tracy</groupId>
<artifactId>Search</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Search</name>
<description>Search</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.kie.modules/com-fasterxml-jackson -->
<dependency>
<groupId>org.kie.modules</groupId>
<artifactId>com-fasterxml-jackson</artifactId>
<version>6.5.0.Final</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
- 项目信息
二、Elasticsearch数据库搭建
0.部署Elasticsearch和kibana服务
使用教程之前写过了:博客
按照步骤搭建起Elasticsearch和kibana服务。
部署好服务之后,创建两个索引text和claim,与后端代码对应起来。
1.SpringBoot整合Elasticsearch
整合教程之前也写过了:博客
2.爬虫获得数据来源
数据爬虫 -> 解析 -> 转为json
数据是根据自己写的爬虫程序获得,简单来说,就是通过已有的一个专利申请号列表去EPO网站上爬取对应的权利书数据。爬取并整理后的数据放在了项目的statics目录下的json文件夹中。 由于不想触及一些版权的问题,因此仅展示其中的几百条数据。
- 代码如下:
import json
import re
from selenium import webdriver
from selenium.webdriver.common.by import By
from scrapy.selector import Selector
def init():
# 1 初始化
option = webdriver.EdgeOptions()
# 这里添加edge的启动文件=>chrome的话添加chrome.exe的绝对路径
option.binary_location = r'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe'
# 这里添加的是driver的绝对路径
driver = webdriver.Edge(r'D:\setup\edgedriver_win64\msedgedriver.exe', options=option)
return driver
# 爬取数据
def down(driver, patent_id, path):
url = "https://worldwide.espacenet.com/patent/search?q=" + patent_id
dict_claims = {
"_id": patent_id,
"_source": {
}
}
# 2 获取元素
try:
driver.minimize_window()
driver.get(url)
driver.implicitly_wait(30)
driver.find_element(by=By.CLASS_NAME, value='search')
# time.sleep(1)
driver.find_element(by=By.XPATH, value='//*[contains(@data-qa,"claimsTab_resultDescription")]').click()
driver.find_element(by=By.XPATH, value='//*[contains(@class,"text-block__content--3_ryPSrw")]')
# time.sleep(1)
# 3 获取元素中的数据
text = driver.find_element(by=By.XPATH, value='//body').get_attribute('innerHTML')
html = Selector(text=text)
text = html.xpath('//*[contains(@class, "text-block__content--3_ryPSrw")]')[0].xpath('string(.)').get()
# 4 处理获取到的text
pattern = r'[0-9]+\.\s'
list = re.split(pattern, text)
for i in range(len(list)):
if len(list[i]) != 0:
dict_claims["_source"][str(i)]=list[i].strip()
# 把爬取到的数据存放到path中
if len(dict_claims["_source"])!=0:
with open(file=path, mode='a', encoding='utf-8') as f:
f.write(json.dumps(dict_claims) + "\n")
print("【获取成功】")
except Exception as e:
# open(file='cited_ids_balanced_failed.txt', mode='a', encoding="utf-8").write(patent_id.strip()+"\n")
print(e)
pass
if __name__ == '__main__':
f_read = open(file='../2 读取专利号/cited_ids_balanced_failed.txt', mode='r', encoding="utf-8")
path_original = 'data_cited.json'
driver = init()
for line in f_read:
patent_id = line.strip()
print(patent_id)
down(driver, patent_id, path_original)
3.导入数据
执行命令将claim.json和text.json分别导入索引claim和索引text中去。
0 安装npm工具
apt install npm -g
1 安装elasticdump插件
npm install elasticdump -g
2 启动es服务
3 通过json文件导入数据
elasticdump --input ./文件名.json --output "http://服务器内网ip:9200/索引名"
三、使用Redis进行接口限流
0.整合Redis
之前写的教程:博客
1.导入Redis模块代码
将仓库中RedisConfig类和AccessLimit类粘贴到项目中。
- 增加yml配置:
time表示限流的单位时间(s),access表示在time s时间内每个接口最多可以访问的次数。
spring:
elasticsearch:
rest:
uris: http://es???ip:9200
redis:
host: 服务器ip
database: 0
port: 6379
# 自定义配置变量
redis:
N: 1000
time: 60
access: 1000
2.实现AOP限流
package com.tracy.search.util;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class AccessLimitAspect {
@Autowired
AccessLimit accessLimit;
@Before("execution(* com.tracy.search.controller..*.*(..))")
public void checkLimit(JoinPoint joinPoint) {
String signature=joinPoint.getTarget().getClass().getName()+"."+joinPoint.getSignature().getName()+"()";
if(!accessLimit.accessLimit(signature)){
throw new SecurityException("达到了限流上限!");
}
}
}
controller包下的全部接口将会被拦截限流。
四、指标分析模块
1.功能概述
使用Redis+AOP统计检索系统的访问次数、访问人数、热点搜索词、热门用户。
- 访问次数: Hash存储,Date为key,次数为value。按日统计。
- 访问人数: Hash,Date为key,次数为value,按日统计。Set用于用于每日的user ip去重。
- 热点搜索词: Zset,score为搜索次数。
- 热门用户: Zset,score为访问次数。
2.获取指标
- 增加yml配置:
spring:
elasticsearch:
rest:
uris: http://es???ip:9200
redis:
host: 服务器ip
database: 0
port: 6379
# 自定义配置变量
redis:
N: 1000
hotUser: 1000
hotKeyword: 1000
time: 60
access: 1000
- controller:
package com.tracy.search.controller;
import com.tracy.search.service.AnalysisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@RestController
@RequestMapping("/analysis")
public class AnalysisController {
@Autowired
AnalysisService analysisService;
@GetMapping("/hotUser")
public List<String> hotUser(){
return analysisService.hot("HotUser");
}
@GetMapping("/hotKeyword")
public List<String> hotKeyword(){
return analysisService.hot("HotKeyword");
}
@GetMapping("/vv")
public HashMap<Date,Integer> vv(@RequestBody List<Date> dates){
return analysisService.v(dates,"VV");
}
@GetMapping("/uv")
public HashMap<Date,Integer> uv(@RequestBody List<Date> dates){
return analysisService.v(dates