建立网页索引
经常想搜某个文件夹、站点内的所有内容,而网页会套网页、文件夹会套文件夹,没想到有什么特别好的搜索工具能递归地找出所有内容,于是想到要不把数据都爬到es再提供全文查询,形成自己的网页知识库。
使用
需要先搭建ES环境,可以参考我记录的ES使用方法:使用 ES。
HTTP
提供HTTP接口:PageCrawlController
抓取POST: localhost:8080/page/crawl
1 | { |
查询GET: localhost:8080/page/crawl
1 | { |
postman
localhost:9200/page/page/_search
1 | { |
爬虫代码
- 读取网页内容
网页是html格式的,为了方便我直接选择用jsoup解析,网页中有很多标签,我需要做的就是读取这些标签中的内容,期间注意过滤无效的标签,比如style、script这种;1
2
3
4
5
6
7
8
9
10Elements allElements = doc.getAllElements();
StringBuilder contentBuilder = new StringBuilder();
for (Element e : allElements) {
// 一些特殊标签忽略,比如style这种
if (excludeTags.contains(e.tag().getName())) {
continue;
}
contentBuilder.append(" ").append(e.ownText());
}
page.setContent(contentBuilder.toString()); - 递归读取
网页通过链接互相关联,读取网页后解析出其中的<a>
、<link>
即可得到关联网页的内容。
我这波忙活的主要目的其实也是尽量读取更多的数据供查询,不然和直接打开网页查询没有区别。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 递归访问子链接
Set<String> childUrls = Sets.newHashSet();
Elements elements = doc.getAllElements();
for (Element element : elements) {
List<String> as = getChildUrls(element, "a");
List<String> links = getChildUrls(element, "link");
childUrls.addAll(as);
childUrls.addAll(links);
}
// 过滤无效的
childUrls = childUrls.stream()
.filter(u -> isUrlValid(crawlId, u))
.collect(Collectors.toSet());
log.info("找出的子链接, childUrls:{}", childUrls);
page.getAs().addAll(childUrls);
for (String childUrl : childUrls) {
// 递归爬
threadPool.execute(new CrawlTask(crawlId, childUrl, depth - 1));
}
索引建立代码
使用ES的代码就不多说了,就列一下用到的指令了。
创建文档POST: localhost:9200/page/page/123
1 | { |
搜索文档GET: localhost:9200/page/page/_search
1 | { |
- 搜索时,因为我更倾向于匹配title,因此用bool+multi_match查询多个字段,并用boost指定title的权重更高。
- 需要注意的是elasticsearch客户端的版本要和服务器的版本保持一致,不然可能发生各种问题,比如某些参数不支持之类的。