Java中的多线程Geo Web爬网程序


本文提供了一个称为Mowglee的Web爬网系统的实现,该系统使用地理区域作为爬网的主要分类标准。而且,它以多线程模式运行,该模式为机器人的排除协议,站点地图生成,数据分类器,数据分析器以及用于构建Web爬网程序的通用框架提供了默认实现。该实现是在核心Java中进行的。Mowglee是Java中的多线程地理网络爬虫。

为此,您应该具有中级到专家级的Java核心技能,了解Java中多线程的复杂性,并了解Web爬网程序的实际用法和需求。

您将学到什么

如何在核心Java中编写简单且基于分布式节点的Web搜寻器。

如何设计网络爬虫以实现地理相似性。

如何编写基于多线程或异步任务执行器的搜寻器。

如何编写具有模块化或可插入体系结构的Web爬网程序。

如何分析多种类型的结构化或非结构化数据。(最少覆盖)

地理搜寻

我在这里描述的爬网系统可以在更高的可达性方面最大程度地发挥地理渗透性。它使用特定地理位置的最重要或吞吐量更高的超链接作为起点或爬网场所。吞吐量指的是对于给定地理位置具有更高数据相关性的许多变化的链接,文本或媒体。它是使用Java中的异步任务执行和多线程概念开发的。

搜寻器称为Mowglee。最好保持“用户代理”名称相同,但是您可以添加自己的变体。例如,如果要添加单词“ raremile”以标识您的变体,请重命名用户代理“ mowglee-raremile”。在尝试运行此程序之前,请确保已在系统上安装了JDK 1.6+。其中一些类具有自己的main() 方法,但它们仅用于单元测试。

运行该应用程序的主要类是in.co.mowglee.crawl.core.Mowglee。您也可以在运行捆绑的JAR文件dist使用java –jar mowglee.jar 。如果将JDK 6用于执行(推荐),则可以jvisualvm用于性能分析。

Mowglee的核心爬网系统使用爬网程序的层次结构进行有效的爬网。是一个类,它依次调用Mowglee中的所有爬网类型:静态爬网,外围爬网和站点爬网。 MowgleeCrawl

MowgleeStaticCrawl是抓取过程的入门课程。这将读取静态地理主页或爬网主页。您可以为每个地理位置配置多个爬网主页,然后为每个爬网主页启动一个MowgleeStaticCrawl过程。您可以将其可视化为多主体系统的非常松散的表示形式。您可以根据需要配置默认的安全等待时间十秒。这是为了确保在开始主爬网之前,所有数据都可以从其他正在运行的进程或其他正在运行的线程获得。

MowgleePeripheryCrawl是第一阶段爬网程序,可从给定页面或超链接中推导顶级域。它的唯一目的是使MowgleeSiteCrawl(第2遍)更容易且更可测量。外围爬网过程还可以用于删除跨爬网的所有重复的顶级域,以便为下一次传递付出更多的精力。在Pass 1中,我们仅关注链接,而不关注数据。

MowgleeSiteCrawl是Pass 2搜寻器,用于使用每个JDK 6执行程序服务实例化各个线程池MowgleeSite。在此阶段,Mowglee爬网过程非常广泛,并且在要检测的数据类型方面非常侵入。在Pass 2中,我们将链接类型分为协议,图像,视频或音频,并且我们还尝试获取有关页面元数据的信息。此阶段最重要的方面是我们以动态但可控的方式进行分析,因为我们尝试根据站点的页面数来增加线程池的大小。

Mowglee被组织为每个爬网通行证中的一组工人。对于通行证1,实际的阅读和演绎工作由完成MowgleePeripheryWorker。 对于Pass 2,阅读和分析链接的工作由完成MowgleeSiteWorker。在此期间使用的帮助程序类包括数据分析器,如后面所述。

MowgleePeripheryWorker 使用MowgleeDomainMap 用于存储的顶级域。最重要的代码行在其中,MowgleeUrlStream 用于打开任何给定URL的套接字并读取其内容,这在下面提供。

StringBuffer httpUrlContents = new StringBuffer();

   InputStream inputStream = null;

    InputStreamReader inputStreamReader = null;

    MowgleeLogger mowgleeLogger = MowgleeLogger.getInstance("FILE");

    // Check if the url is http

    try {


        if (crawlMode.equals(MowgleeConstants.MODE_STATIC_CRAWL)) {

        mowgleeLogger.log("trying to open the file from " + httpUrl, MowgleeUrlStream.class);

        inputStream = new FileInputStream(new File(httpUrl));


        inputStreamReader = new InputStreamReader(inputStream);


        } else {

        mowgleeLogger.log("trying to open a socket to " + httpUrl, MowgleeUrlStream.class);

        inputStream = new URL(httpUrl).openStream();


        inputStreamReader = new InputStreamReader(inputStream);

        }


        // defensive

        StringBuffer urlContents = new StringBuffer();

        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

        String currentLine = bufferedReader.readLine();


        while (currentLine != null) {

        urlContents.append(currentLine);

        currentLine = bufferedReader.readLine();

        }


        if (httpUrl != null & httpUrl.trim().length() > 0) {

        MowgleePageReader mowgleePageReader = new MowgleePageReader();

        mowgleePageReader.read(httpUrl, urlContents, crawlMode);


        mowgleeLogger.log("the size of read contents are " + new String(urlContents).trim().length(),

            MowgleeUrlStream.class);

        }


        // severe error fixed - possible memory leak in case of an exception! - [connection leak fixed]

        // inputStream.close();

    } catch (FileNotFoundException e) {


        mowgleeLogger.log("the url was not found on the server due to " + e.getLocalizedMessage(),

            MowgleeUrlStream.class);
    } catch (MalformedURLException e) {
        mowgleeLogger.log("the url was either malformed or does not exist", MowgleeUrlStream.class);
    } catch (IOException e) {
        mowgleeLogger.log("an error occured while reading the url due to " + e.getLocalizedMessage(),
            MowgleeUrlStream.class);
    } finally {
        try {
            // close the connection / file input stream 
            if (inputStream != null)
                inputStream.close();
        } catch (IOException e) {
            mowgleeLogger.log("an error occured while closing the connection " + e.getLocalizedMessage(),
            MowgleeUrlStream.class);
        }
    }

清单1:Mowglee-打开Stream / Crawling。

2.png

在Mowglee中,存在用于多种类型的数据和媒体的各种分析器。作为此代码库的一部分实现的分析器为MowgleeLinkAnalyzer。它MowgleeSiteMap 用作给定顶级域内所有链接的内存存储。 它还维护给定顶级域中所有已爬网和已分析超链接的已访问URL和已收集URL的列表。

3.png

MowgleeGarbageCollector 是守护程序线程,在运行主应用程序时实例化并启动。由于每个线程实例化了大量对象,因此该线程尝试在内存使用的安全限制内控制和强制执行内部垃圾回收机制。MowgleeLogger 为Mowglee中的所有类型的记录器提供抽象类。另外,RobotsExclusionProtocol在下提供了一个实现MowgleeRobotsExclusionFilter。 这是继承自MowgleeCrawlFilter。与爬虫系统功能更接近的所有其他类型的过滤器都可以从该特定类扩展。

MowgleeCommonUtils 提供了许多常见的辅助功能,例如deduceTopLevelDomain()owgleeSitemapGenerator 是用于根据站点地图协议生成站点地图的占位符类,并且是更广泛或自定义实施的起点。可以添加用于分析图像,视频和音频的实现。仅提供占位符。

应用领域 以下是此类Web爬虫的理想应用。

网站治理和政府执法 使用此系统可以执行任何本地化或自定义的地理规则。同样,通过人工推论或出于任何管理目的自动检测数据模式进行的任何类型的分类都可以通过生成的数据轻松完成。

排名网站和链接 可以对来自该站点的数据执行进一步定位到特定地理区域或特定区域的搜索引擎系统的站点和链接的排名。在同一地理区域内查找关系和单击链接的方式会更容易。

分析和数据模式 可以使用第三方或自定义工具来分析从该爬网程序收集的数据,以进一步创建知识。同样,可以从生成的数据量中创建相关的数字存储库。

基于关键字的广告 一个重要的应用将是基于从此爬网系统收集的数据来驱动广告。分析器可用于查找特定的术语,关键字,词组,并嵌入相关的广告或为广告商生成建议。

增强功能 以下是涉及此类别的Web爬网程序的一些增强功能。

使用图数据库存储 您可以添加图形数据库的实现或使用流行的NoSQL图形存储选项之一。起点是MowgleePersistenceCore 课程。

各种分析仪 您可以根据自己的组织或学术需求添加更多分析仪。您必须扩展的基类是MowgleeAnalyzer ,您可以参考MowgleeLinkAnalyzer以了解分析器的实现。

重点分类器 您可以添加分类器或插件的层次结构,以根据术语,关键字,地理术语或短语自动对数据进行分类。一个例子是MowgleeReligiousAbusePlugin。

复杂的推论机制 可以添加更复杂的推论机制,以创建特定地理位置内的进一步爬网相关性。这包括针对特定的爬网会话忽略地理区域,国家或地区之外的链接。在较高级别,例如在大陆级别,可以将其实现为协作式多代理系统。

网站地图生成 这里提供了站点地图生成机制的起点。您也可以在内部使用其他站点地图生成库,也可以开发自己的自定义实现来增强此功能。

结论 Mowglee不保证将创建站点地图或将其用于爬网。它使用一种async机制,并确保也爬网了从站点内部到自身可能无法访问的所有链接。Mowglee当前没有终止机制。我提供了一个占位符,供您根据使用情况决定。这可以基于爬网的顶级域的数量,数据量,爬网的页面数,地理边界,要爬网的站点类型或任意机制。

请关闭系统上的所有应用程序,以将所有可用的系统资源专用于Mowglee。默认的起始爬网点是http://www.timesofindia.com。您也可以尝试通过将起始爬网点更改为其他站点来尝试。在当前表单中,您可以使用该mowglee.crawl文件读取爬网分析。没有提供其他存储机制。您可以在诸如EditPlus之类的编辑器中将此文件保持打开状态,以连续监视其内容。

本文应该为您构建分层的多线程搜寻器提供了良好的基础,尤其是对于需要基于地理分类和相似性的应用程序而言。它还应帮助您节省时间(通过重新使用此代码库),以便以此来构建搜寻器或应用程序。您可能还希望如上所述在Mowglee的基础上构建增强功能,然后将其发布回DZone,以使整个社区受益!


原文链接:http://codingdict.com/