iis服务器助手广告
返回顶部
首页 > 资讯 > 后端开发 > Python >利用Java实现网站聚合工具
  • 434
分享到

利用Java实现网站聚合工具

2024-04-02 19:04:59 434人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录原理实现代码页面下载解析返回值中的所有链接解析返回值中的title去除返回值中的标签分词获取分词结果的数量前十个遍历网站连通块调用测试互联网上有数以万亿计的网站,每个网站大都具有

互联网上有数以万亿计的网站,每个网站大都具有一定的功能。搜索引擎虽然对互联网上的部分网站建立了索引,但是其作为一个大而全的搜索系统,无法很好的定位到一些特殊的需求,基于这样的背景,我尝试了写了一个网站数据聚合的程序。现在将原理和实现代码分享给大家。

原理

可以把互联网上的网站看做一张巨大的连通图,不同的网站处于不同的连通块中,然后以广度优先算法遍历这个连通块,就能找到所有的网站域名,利用广度优先算法遍历该连通块的结构可以抽象为:

然后,我们对该网站的返回内容进行分词,剔除无意义的词语和标点符号,就得出该网站首页的关键词排序,我们可以取词频在(10,50)区间范围内的为关键词,然后将这些关键词作为网站主题,把网站的信息放到以该词为名字的markdown文件中备用。

同理,我们也对该网站返回内容的title部分进行分词,因为title是网站开发者对网站功能的浓缩,也比较重要,同理,也将这些关键词作为网站主题,把网站的信息放到以该词为名字的markdown文件中备用。

最后,我们只需要从这些文件中人工做筛选,或者以这些数据放到elasticsearch中,做关键词搜索引擎即可。以达到想用的时候随时去拿的目的。​

不过,当你遍历连通块没有收敛时,得到的数据还是很少的,某些分类往往只有一两个网站。

实现代码

页面下载

页面下载我使用的是HttpClient,前期考虑用playwrite来做,但是两者性能差距太大,后者效率太低了,所以舍弃了部分准确性(即WEB2.0技术的网站,前者无法拿到数据),所以准确的说我实现的仅仅是web1.0的网站分类搜索引擎的页面下载功能。

public SendReq.ResBody doRequest(String url, String method, Map<String, Object> params) {
    String urlTrue = url;
    SendReq.ResBody resBody = SendReq.sendReq(urlTrue, method, params, defaultHeaders());
    return resBody;
}

其中,SendReq是我封装的一个httpClient的类,只是实现了一个页面下载的功能,你可以替换为RestTemplate或者别的发起http(s)请求的方法。​

解析返回值中的所有链接

因为是连通块遍历,那么定义的连通网站就是该网站首页里面所有的外链的域名所在的站,所以我们需要提取链接,直接使用正则表达式提取即可。

public static List<String> getUrls(String htmlText) {
    Pattern pattern = Pattern.compile("(http|https):\\/\\/[A-Za-z0-9_\\-\\+.:?&@=\\/%#,;]*");
    Matcher matcher = pattern.matcher(htmlText);
    Set<String> ans = new HashSet<>();
    while (matcher.find()){
        ans.add(DomainUtils.getDomainWithCompleteDomain(matcher.group()));
    }
    return new ArrayList<>(ans);
}

解析返回值中的title

title是网站开发者对网站功能的浓缩,所以很有必要将title解析出来做进一步处理

public static String getTitle(String htmlText){
    Pattern pattern = Pattern.compile("(?<=title\\>).*(?=</title)");
    Matcher matcher = pattern.matcher(htmlText);
    Set<String> ans = new HashSet<>();
    while (matcher.find()){
        return matcher.group();
    }
    return "";
}

去除返回值中的标签

因为后续步骤需要对网站返回值进行分词,所以需要对页面中的标签和代码进行去除。

public static String getContent(String html) {
    String ans = "";
    try {
        html = StringEscapeUtils.unescapeHtml4(html);
        html = delHTMLTag(html);
        html = htmlTextFORMat(html);
        return html;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return ans;
}

public static String delHTMLTag(String htmlStr) {
    String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
    String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式
    String regEx_html = "<[^>]+>"; //定义HTML标签的正则表达式

    Pattern p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
    Matcher m_script = p_script.matcher(htmlStr);
    htmlStr = m_script.replaceAll(""); //过滤script标签

    Pattern p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
    Matcher m_style = p_style.matcher(htmlStr);
    htmlStr = m_style.replaceAll(""); //过滤style标签

    Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
    Matcher m_html = p_html.matcher(htmlStr);
    htmlStr = m_html.replaceAll(""); //过滤html标签

    return htmlStr.trim();
}

分词

分词算法使用之前讲NLP入门的文章里面提到的hanlp即可

private static Pattern ignoreWords = Pattern.compile("[,.0-9_\\- ,、:。;;\\]\\[\\/!()【】*?“”()+:|\"%~<>——]+");

public static Set<Word> separateWordAndReturnUnit(String text) {
    Segment segment = HanLP.newSegment().enableOffset(true);
    Set<Word> detectorUnits = new HashSet<>();
    Map<Integer, Word> detectorUnitMap = new HashMap<>();
    List<Term> terms = segment.seg(text);
    for (Term term : terms) {
        Matcher matcher = ignoreWords.matcher(term.word);
        if (!matcher.find() && term.word.length() > 1 && !term.word.contains("�")) {
            Integer hashCode = term.word.hashCode();
            Word detectorUnit = detectorUnitMap.get(hashCode);
            if (Objects.nonNull(detectorUnit)) {
                detectorUnit.setCount(detectorUnit.getCount() + 1);
            } else {
                detectorUnit = new Word();
                detectorUnit.setWord(term.word.trim());
                detectorUnit.setCount(1);
                detectorUnitMap.put(hashCode, detectorUnit);
                detectorUnits.add(detectorUnit);
            }
        }
    }
    return detectorUnits;
}

获取分词结果的数量前十个

这里为了去掉词频过多的词的干扰,所以只取词频小于50的词的前十

public static List<String> print2List(List<Word> tmp,int cnt){
    PriorityQueue<Word> words = new PriorityQueue<>();
    List<String> ans = new ArrayList<>();
    for (Word word : tmp) {
        words.add(word);
    }
    int count = 0;
    while (!words.isEmpty()) {
        Word word = words.poll();
        if (word.getCount()<50){
            ans.add(word.getWord() + " " + word.getCount());
            count ++;
            if (count >= cnt){
                break;
            }
        }
    }
    return ans;
}

方法就是放到优先队列中一个一个取出来,优先队列是使用大顶堆实现的,所以取出来一定是有序的。如果想了解大顶堆的朋友,可以看我前面的文章。
值得注意的是,优先队列中放入的类必须是可排序的,所以,这里的Word也是可排序的,简化的代码如下:

public class Word implements Comparable{
    private String word;
    private Integer count = 0;

    ... ...

    @Override
    public int compareTo(Object o) {
        if (this.count >= ((Word)o).count){
            return -1;
        }else {
            return 1;
        }
    }
}

好了,现在准备工作已经做好了。下面开始实现程序逻辑部分。

遍历网站连通块

利用广度优先遍历网站连通块,之前的文章有专门讲利用队列写广度优先遍历。现在就使用该方法。

public void doTask() {
    String root = "http://" + this.domain + "/";
    Queue<String> urls = new LinkedList<>();
    urls.add(root);
    Set<String> tmpDomains = new HashSet<>();
    tmpDomains.add(DomainUtils.getDomainWithCompleteDomain(root));
    while (!urls.isEmpty()) {
        String url = urls.poll();
        SendReq.ResBody html = doRequest(url, "GET", new HashMap<>());
        System.out.println("当前的请求为 " + url + " 队列的大小为 " + urls.size() + " 结果为" + html.getCode());
        if (html.getCode().equals(0)) {
            ignoreSet.add(DomainUtils.getDomainWithCompleteDomain(url));
            try {
                GenerateFile.createFile2("moneyframework/generate/ignore", "demo.txt", ignoreSet.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
            continue;
        }

        OnePage onePage = new OnePage();
        onePage.setUrl(url);
        onePage.setDomain(DomainUtils.getDomainWithCompleteDomain(url));
        onePage.setCode(html.getCode());
        String title = HtmlUtil.getTitle(html.getResponce()).trim();
        if (!StringUtils.hasText(title) || title.length() > 100 || title.contains("�")) continue;
        onePage.setTitle(title);
        String content = HtmlUtil.getContent(html.getResponce());
        Set<Word> words = Nlp.separateWordAndReturnUnit(content);
        List<String> wordStr = Nlp.print2List(new ArrayList<>(words), 10);
        handleWord(wordStr, DomainUtils.getDomainWithCompleteDomain(url), title);
        onePage.setContent(wordStr.toString());
        if (html.getCode().equals(200)) {
            List<String> domains = HtmlUtil.getUrls(html.getResponce());
            for (String domain : domains) {
                int flag = 0;
                for (String i : ignoreSet) {
                    if (domain.endsWith(i)) {
                        flag = 1;
                        break;
                    }
                }
                if (flag == 1) continue;
                if (StringUtils.hasText(domain.trim())) {
                    if (!tmpDomains.contains(domain)) {
                        tmpDomains.add(domain);
                        urls.add("http://" + domain + "/");
                    }
                }
            }
        }
    }
}

调用测试

@Service
public class Task {

    @PostConstruct
    public void init(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        HttpClientCrawl clientCrawl = new HttpClientCrawl("http://www.mengwa.store/");
                        clientCrawl.doTask();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

大家也可以用自己的个人博客作为起点试一下,看下自己在哪个连通块里面。

以上就是利用Java实现网站聚合工具的详细内容,更多关于Java网站聚合的资料请关注编程网其它相关文章!

--结束END--

本文标题: 利用Java实现网站聚合工具

本文链接: https://www.lsjlt.com/news/164029.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 利用Java实现网站聚合工具
    目录原理实现代码页面下载解析返回值中的所有链接解析返回值中的title去除返回值中的标签分词获取分词结果的数量前十个遍历网站连通块调用测试互联网上有数以万亿计的网站,每个网站大都具有...
    99+
    2024-04-02
  • 怎么用Java实现网站聚合工具
    这篇文章主要介绍“怎么用Java实现网站聚合工具”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么用Java实现网站聚合工具”文章能帮助大家解决问题。原理可以把互联网上的网站看做一张巨大的连通图,不...
    99+
    2023-06-29
  • Python+tkinter实现网站下载工具
    目录前言开发环境本次项目案例步骤先展示下完成品的效果界面导入模块先创建个窗口功能按键主要功能代码编写功能一功能二功能三前言 最近很多同学想问我,怎么把几个代码的功能集合到一起? 很简...
    99+
    2023-03-07
    Python tkinter网站下载工具 Python tkinter下载工具 Python 网站下载
  • 怎么使用Python+tkinter实现网站下载工具
    今天小编给大家分享一下怎么使用Python+tkinter实现网站下载工具的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。开发...
    99+
    2023-07-05
  • 利用Java实现在PDF中添加工具提示
    目录导入jar包添加工具提示ToolTip本文,将介绍如何通过Java后端程序代码在PDF中创建工具提示。添加工具提示后,当鼠标悬停在页面上的元素时,将显示工具提示内容。 导入jar...
    99+
    2024-04-02
  • 利用Java怎么实现一个超时工具类
    本文章向大家介绍利用Java怎么实现一个超时工具类的基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,实现了面向对象理论,允许程...
    99+
    2023-06-06
  • Java利用Reflect实现封装Excel导出工具类
    目录定义ExcelExportEnum定义导出方法校验入参利用java反射获取Service中的所有method提取method中的入参对象,获取其Class传入参数,调用导出方法注...
    99+
    2022-11-13
    Java Reflect封装Excel导出工具类 Java Excel导出 Java Reflect
  • java利用Future实现多线程执行与结果聚合实例代码
    目录场景解决总结场景 网站智能问答场景,需要对多个分类查询,结果聚合展示 由于每种分类都有自己的业务逻辑,有的需要查询数据库中间库,有的需要查询elasticsearch搜索引擎,有...
    99+
    2024-04-02
  • 利用Python实现Picgo图床工具
    目录一、PyPicGo1、安装2、配置3、使用4、支持的图床5、支持的插件6、Uploader上传器7、插件系统8、开发一、PyPicGo PyPicGo 是一款图床工具,是Pic...
    99+
    2024-04-02
  • sql综合利用工具有哪些
    以下是几个常用的SQL综合利用工具:1. SQLmap:一个自动化的SQL注入工具,可用于检测和利用SQL注入漏洞。2. Metas...
    99+
    2023-06-08
    sql综合利用工具 sql
  • 利用Java工具类Hutool实现验证码校验功能
    目录Hutool工具类介绍Hutool实现验证码生成测试验证码生成其他样式的验证码第一篇是纯利用现有JDK提供的绘图类(ImageIO)类制作,这个过程比较复杂且需要了解ImageI...
    99+
    2022-11-13
    Hutool生成验证码 Hutool工具类 java验证码校验
  • 如何利用Python实现Picgo图床工具
    这篇文章主要介绍了如何利用Python实现Picgo图床工具,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、PyPicGoPyPicGo 是一款图床工具,是PicGo是Py...
    99+
    2023-06-25
  • 如何在mongoDB中利用java处理聚合函数
    本篇文章给大家分享的是有关如何在mongoDB中利用java处理聚合函数,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。需要对document中...
    99+
    2024-04-02
  • 网站截图工具EyeWitness怎么用
    这篇文章主要介绍了网站截图工具EyeWitness怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。网站截图工具EyeWitness在网页分析和取证中,往往需要大批量的网站...
    99+
    2023-06-04
  • 网站压力测试工具-ab工具apachebench使用过程
    目录关于压力测试相关名词解释ab工具简介下载ab工具启动ab工具开始测试测试结果分析关于登录的问题总结apache bench是apache自带的压力测试工具。ab不仅可以对apac...
    99+
    2022-11-21
    网站压力测试工具 ab工具 apache bench
  • 如何利用python实现kmeans聚类
    目录一、先上手撸代码!二、接下来是调库代码!(sklearn)附:对k-means算法的认识总结一、先上手撸代码! 1、首先是导入所需要的库和数据 import pandas as ...
    99+
    2024-04-02
  • java利用Future实现多线程执行与结果聚合的代码怎么写
    java利用Future实现多线程执行与结果聚合的代码怎么写,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。场景网站智能问答场景,需要对多个分类查询,结果聚合展示由于每种分类...
    99+
    2023-06-22
  • 利用Python的PIL工具包实现图片比
     PythonWare公司提供了免费的图像处理工具包PIL(Python Image Library),该软件包提供了基本的图像处理功能,本文介绍了使用PIL工具包中的Image模块进行比对的过程。                    ...
    99+
    2023-01-31
    工具包 图片 Python
  • springboot怎么利用@Aspect实现日志工具类
    这篇文章主要介绍了springboot怎么利用@Aspect实现日志工具类的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇springboot怎么利用@Aspect实现日志工具类文章都会有所收获,下面我们一起来看...
    99+
    2023-06-29
  • 利用Python实现网站自动签到
    目录前情提要准备工作代码及讲解小结前情提要 小五收藏了一些论坛网站,经常需要自己登录签到,以此来获得积分金币等等。 步骤倒是并不复杂,只需要填写账号密码登录,然后点击签到即可。 但...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作