Java编写一个简单的Web爬虫

World Wide Web,缩写WWW、W3或者Web,是一个因特网的相互连接的超文本文档。使用Web浏览器,可以查看一个文档,以及跟随超链接查看其它文档。这里,我们将开发一个简单的程序,可以跟随超链接来自动遍历Web。这类程序通常称为Web爬虫。为简单起见,我们的程序跟随以http://开始的超链接。

在写程序之前有必要了解一下什么是URL(Uniform Resource Location),即Web上的文件提供的唯一地址,可以叫做统一资源定位器,知道了这个便可以从Web上访问数据。

为了读取一个文件,首先要使用java.net.URL类的构造方法,为该文件创建一个URL对象。例如,下面给出的语句为http://www.google.com/index.html创建一个URL对象。

try {
   URL url1=new URL("http://www.google.com/index.html");
}
catch (MalformedURLException ex) {
   ex.printStackTrace();
}

创建一个URL对象后,可以使用URL类中定义的openStream()方法来打开输入流和用输入流创建Scanner对象。
Scanner input=new Scaner(url.openStream());

现在可以从输入流读取数据了,如同从本地文件中读取数据一样。

如图给出了一个遍历Web的例子。从一个包含了三个分别名为URL1,URL2,URL3的网址的页面开始,跟随URL2将到达一个包含两个名为URL21和URL22的网址的页面,跟随URL3将到达一个包含名为URL31、URL32、URL33、URL44的网址的页面。可以继续跟随新的超链接对Web进行遍历。这个过程可以一直进行下去,但是我们将在遍历了100个页面后退出程序。

Java编写一个简单的Web爬虫_第1张图片

程序跟随URL来遍历Web。为保证每一个URL只被遍历一次,程序包含两个网址的列表。一个列表保存将被遍历的网址,另一个保存已经被遍历的网址。程序的算法描述如下:

将起始URL添加到名为listOfPendingURLs的列表中;
    当listOfPendingURLs不为空并且listOfTraversedURLs的长度<=100 {
        从listOfPendingURLs移除一个URL;
        如果该URL不在listOfTraversedURLs中 {
            将其添加到listOfTraversedURLs中;
            显示该URL;
            读取该URL的页面,并且对该页面中包含的每个URL进行如下操作 {
                如果不在listOfPendingURLs中,则将其添加到listOfPendingURLs中;
            }
        }
    }

实现该算法的完整程序如下:

package com.company;

import java.util.Scanner;
import java.util.ArrayList;

public class WebCrawler {
    public static void main(String[] args) {
        java.util.Scanner input=new java.util.Scanner(System.in);
        System.out.print("Enter a URL: ");
        String url=input.nextLine();
        craweler(url);
    }

    public static void craweler(String startingURL) {
        ArrayList listOfPendingURLs=new ArrayList<>();
        ArrayList listOfTraversedURLs=new ArrayList<>();
//将起始的URL添加到listOfPendingURLs,然后通过一个while循环重复处理listOfPendingURLs中每一个URL
        listOfPendingURLs.add(startingURL);
        while(!listOfPendingURLs.isEmpty()&&listOfTraversedURLs.size()<=100) {
        //将列表中第一个RUL去除,如果该RUL没有被处理过则对其进行处理
            String urlString=listOfPendingURLs.remove(0);
            if(!listOfTraversedURLs.contains(urlString)) {
                listOfTraversedURLs.add(urlString);
                System.out.println("Crawl"+urlString);
//程序使用foreach循环,将页面中的每个不存在listOfTraversedURLs中的URL添加到listOfPendingURLs中
                for(String s:getSubURLs(urlString)) {
                    if(!listOfTraversedURLs.contains(s)) listOfPendingURLs.add(s);
                }

        }
        }
    }

    public static ArrayList getSubURLs(String urlString) {
        //该方法为每个给定的URL返回一个URL列表
        ArrayList list=new ArrayList<>();
        try {
            java.net.URL url=new java.net.URL(urlString);
            Scanner input=new Scanner(url.openStream());
            int current=0;
            while(input.hasNext()) {
                String line=input.nextLine();//从Web读取每一行
                current=line.indexOf("http:",current);//寻找该行中的URL
                while(current>0) {
                    int endIndex=line.indexOf("\"",current);//假设URL以引号"结束
                    if(endIndex>0) {
                        list.add(line.substring(current,endIndex));//一行中可能包含多个URL,
                        current=line.indexOf("http:",endIndex);//方法继续寻找下一个URL
                    }
                    else current=-1;//如果该行中没有发现URL,curr设为-1
                }
            }
        }
        catch (Exception ex) {
            System.out.println("Error: "+ex.getMessage());
        }
        return list;//页面中包含的URL以一个列表的形式返回
    }
}

运行结果如下:

Java编写一个简单的Web爬虫_第2张图片

你可能感兴趣的:(Java网络编程)