抓取文章保存

212 阅读1分钟

功能

通过Gecco来抓取网站,并存储到elasticsearch中。

可以通过网址搜索elasticsearch中存储的文章列表,可以查看文章内容。

环境

配置

安装elasticsearch

可配

elasticsearch安装ik分词器

elasticsearch.yml

http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true

indices.fielddata.cache.size: 20%
indices.breaker.total.use_real_memory: false
indices.breaker.fielddata.limit: 40%
indices.breaker.request.limit: 40%
indices.breaker.total.limit: 95%

预览

文章列表 文章详细

使用说明

选择一个站点提取文章

通过css选择器选择文章对应的标签 以 https://news.qq.com/ 为例,文章的标题为h1标签,内容为标签类名为content-article的标签,文章地址为任意包含超链接的a标签

新建一个Bean继承HtmlBean,添加注解 @Gecco(matchUrl = {"*"}, pipelines = "articlePipeline", downloader = "htmlUnitDownloder") matchUrl代表匹配的url地址,pipelines指定获取到内容后的处理管道,downloader指定网址的下载方式

@HtmlField(cssPath = "h1")
private String title;
@HtmlField(cssPath = ".content-article")
private String content;
@Href
@HtmlField(cssPath = "a[href]")
private List<String> urls;

新建类public class ArticlePipeline extends BasePipeline<ArticlePipeline.Bean> ,在public void onCapture(Bean bean)可以获得提取到的文章数据,这里可以对文章进行存储。

@Override
public void onCapture(Bean bean) {
    bean.getUrls().forEach(url -> {
        Pattern pattern = Pattern.compile("https://new.qq.com/omn/.*");//匹配的文章地址
        Matcher matcher = pattern.matcher(url);

        if (!matcher.find()) {
            return;
        }
        synchronized (fetchedSet) {
            if (!fetchedSet.contains(url) && fetchedSet.size() < 15) {//最多抓取15篇文章

                log.info(url);
                fetchedSet.add(url);
                DeriveSchedulerContext.into(new HttpGetRequest(url));//添加到抓取队列
            }
        }


    });
    // 保存文章
    String id = MD5.create().digestHex(bean.getContent());
    Article article = new Article();
    article.setId(id);
    article.setTitle(bean.getTitle());
    article.setContent(bean.getContent());
    if (articleRepository.findById(id).isPresent()) {
        article.setCreateAt(new Date());
    } else {
        article.setUpdateAt(new Date());
    }
    articleRepository.save(article);

}

因为抓取的内容是html标签,所有文章的样式需要在article.html中加入才能更好地展现文章内容。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="zh">
<head>
    <meta charset="UTF-8">
    <title>文章列表</title>
    <link rel="stylesheet" href="/css/tx.css">
</head>
<body>
<div class="content">
    <div th:each="item : ${articles} " style="width: 100%;">
        <a th:href="@{'/article/' + ${item.id}}" th:text="${item.title}"></a>
    </div>
</div>
</body>
</html>

源码地址