• 我的第一个开源项目


    地址

    gitee地址,GitHub网速较慢,没有上传到GitHub

    项目介绍

    1. 一个简单的多线程爬虫,具有断点爬取功能,以及自动推测网页编码功能

    2. 使用jdk11+,maven构建,我使用jdk11.0.2时会报错,见https://bugs.openjdk.java.net/browse/JDK-8213202,jdk8却没有,jdk本身的bug,所以我换了最新版的jdk11.0.4

    3. 解析网页主要使用了Jsoup和正则表达式,所以这两个需要会用

    思路

    1. 先有一个或多个具体的初始链接,假如说把这些初始链接的页面类型记为seed

    2. 定义一个规则,规则主要由Jsoup选择器(类似于css选择器)、正则表达式、页面类型type组成,选择器一般定位到a标签。seed页面通过应用规则就可以自动获取标签中符合正则表达式的链接,并将这些链接存储到h2中,这些链接就是下一层要爬取的链接,假如将这些链接所代表的页面记为page1(type设置成了page1)

    3. 重复上一步,也是定义规则,唯一的区别就是应用这些规则的页面不是seed,而是page1页面。也就是说这些规则是有顺序的,除了第一个规则应用于seed页面之外,其余的每一个规则都是应用于上一个规则获取到的页面,以此类推,多少层都可以

    4. 结合示例查看源代码能更快的理解

    示例及说明

    ZongHeng zh = new ZongHeng();
    zh.setCacheDirectory("f:/spider");
    zh.config().setInterval(50).setBreakPoint(false);
    //添加一个初始链接
    zh.addSeed("http://www.zongheng.com/");
    //添加一个规则,按照这个规则在初始链接页面取链接,并将取到的链接代表的页面记为category
    zh.addRule("ul#data-groupdom li a", "http://www.zongheng.com/category/\d+.html", "category");
    //添加规则,在category页面取链接
    zh.addRegex("http://book.zongheng.com/book/\d+.html", "book");
    zh.start();
    

    每一个具体的爬虫都继承自Spider类,上面的代码就定义了一个简单的爬虫。

    1. 第2行:设置缓存目录f:/spider
    2. 第3行:提交任务间隔最大50毫秒,关闭断点爬取
    3. 第4行:添加一个初始链接
    4. 第5行:添加一个规则,按照这个规则在初始链接页面取链接,并将取到的链接代表的页面记为category
    5. 第6行:添加一个规则,按照这个规则在category页面取链接,并将取到的链接代表的页面记为category
    6. 第7行:启动爬虫

    启动后爬虫就能自己去获取符合规则的网页,但获取网页不是我们的最终目的,我们的最终目的是从网页中提取自己需要的信息,所以继承Spider后还有一个必须重写的方法

    @Override
    public void parse(Page page) {
        if (!page.isSeed()) {
            String text = page.urlText();
            System.out.println(text + "---" + page.link() + "---" + page.prevLink());
        }
        if (page.typeEquals("category")) {
            //category页面取得的下层链接的标签的文本去掉空白后长度大于1
            page.setNextLinksFilter(e -> e.hasText() && e.text().replaceAll("\s+", "").length() > 1);
        }
    }
    

    解析主要就是应用Jsoup里面的方法,通过page.getDoc()方法可以获取org.jsoup.nodes.Document对象,或者直接调用page.select(String cssQuery)方法解析,这就不多说了。

    要说一下就是Page里面的3个高阶函数,所谓高阶函数就是接收函数作为参数的函数,这3个函数分别是setNextLinksFilter,setNextInfoFunc,setNextLinkUnary,作用分别是筛选符合条件的链接作为下层链接,携带信息到下一层,链接映射。

    上面的代码就用到了筛选的方法,传入的函数是这样的:函数的参数是org.jsoup.nodes.Element类型的对象,一般代表a标签,函数返回boolean类型,返回值为true的Element才能作为下一层链接的提供者。

    手动获取下层链接

    上面说的是自动获取下层链接,即只需要通过规则爬虫就能一层一层的获取链接,但有时候这样可能行不通,需要手动的获取链接然后添加到下一层,怎么做呢?

    看一下这个例子,这其实完全可以自动获取下层链接,为了演示改成了手动获取下层链接,addByHand(String type)方法看源码知道这也是一个规则,只不过是一个只有type属性的规则而已。

    //添加一个初始链接
    zh.addSeed("http://www.zongheng.com/");
    zh.addByHand("category");
    

    可以看到初始链接后面紧跟一个手动添加规则,记为category

    if (page.isSeed()) {
        //这样还是用规则获取的下层链接,所以这没必要用手动,这里仅作为示例
        page.addNext(Rule.createRule("ul#data-groupdom li a", "http://www.zongheng.com/category/\d+.html"));
    }
    

    然后在seed页面取链接(这些链接所表示的页面就是category页面)加入到下一层,这就是手动添加了

    局限

    • 由于自动缓存的原因,编写好规则并爬取后,如果再次修改规则,如加入筛选条件等,由于从缓存中取数据,此时筛选条件对已经爬取的网页不起作用,要使它起作用,请删除缓存

    • 目前只支持get请求或能转换成get请求的链接

    感谢

  • 相关阅读:
    末学者笔记--KVM虚拟化存储管理(3)
    离线安装docker-ce
    OpenStack各组件的常用命令
    docker容器的基本命令
    nfs samba文件共享服务
    kvm虚拟机管理(创建、连接)
    虚拟化kvm的搭建
    python(pymysql操作数据库)
    三大特征 封装 继承 多态
    面向对象
  • 原文地址:https://www.cnblogs.com/pdzbokey/p/11639779.html
Copyright © 2020-2023  润新知