从网页源读取随机失败 - Java

时间:2016-01-09 03:43:34

标签: java regex url bufferedreader

这是我在Java中遇到的最奇怪的事情。在这种情况下。我尝试在没有任何API的情况下阅读80多个网址(这真的很糟糕)。网页有一种显示我需要的信息的常用方式,因此我通常可以使用一些正则表达式语句找到感兴趣的项目。

这是我想要阅读的示例网页。 Webpage

我有两个非常草率的课程来实现这个目标:

Tester.java。 这里的Main方法只是从我的计算机上读取URL,并且每个方法都从Tools类调用一个方法,该方法返回一个ArrayList。然后它将ArrayList中的所有项添加到一个更大的ArrayList中,这是我想要的输出。我的程序从未实现过这一点。

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class Tester
{
    public static int d2counter = 0;

    public static void main(String[] args)
    {
        ArrayList<String> database = new ArrayList<>(); 
        ArrayList<String> urls = new ArrayList<>(); 

        try
        {           
            FileReader writer = new FileReader("res/URLs.txt");
            BufferedReader reader = new BufferedReader(writer);     

            while (reader.ready())
            {
                urls.add(reader.readLine());
            }

            for (String i : urls)
            {
                System.out.println(++d2counter + " " + i);
                ArrayList<String> temp = Tools.readURL(i);

                for (String h : temp)
                {
                    database.add(h);
                }
            }

            Tools.outputArraysToFile(database, "output.txt");

            reader.close();
        }
        catch (FileNotFoundException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }               
    }
}

Tools.java。这是一个充满静态方法的辅助类。这里唯一感兴趣的方法是readURL()方法。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;

/**
 * Class which will house useful tools for other classes in this program.
 */
public abstract class Tools
{       
    public static ArrayList<String> readURL(String address)
    {
        ArrayList<String> temp = new ArrayList<>();

        try
        {
            // Create a reader to read the webpage.
            BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(address).openStream()));

            // Line variable to be used by Reader.
            String line = "";

            // Phase 1: Navigate to the desired section of the webpage.
            int counter2 = 1;
            while (reader.ready())
            {
                line = reader.readLine();
                counter2++;

                if (line.contains("MAIN CONTENT"))
                {
                    break;
                }
            }

            if (!reader.ready())
            {
                System.err.println("ERROR: Reached bottom of document without finding page title.");
                System.exit(1);
            }

            String name, url, type;
            type = "Default";

            // Find the type.
            for (int i = 0; i < 3; i++)
            {
                line = reader.readLine();

                if (line.matches(".*<B>[A-Za-z\\s]+</b>.*"))
                {
                    line = line.substring(line.indexOf("<B>") + 3, line.indexOf("</b>"));
                    line = line.replace("Normal", "");
                    line = line.replace("Exquisite", "");
                    line = line.replace("Elite", "");
                    line = line.trim();
                    if (line.endsWith("s"))
                    {
                        line = line.substring(0, line.length() - 1);
                    }

                    type = line;
                    break;
                }
            }

            // Phase 2: Add data:
            while (!line.contains("END MAIN CONTENT"))
            {
                line = reader.readLine();

                if (line.contains(".gif"))
                {
                    line = line.replaceFirst(".*src=\"", "");
                    url = "classic.battle.net" + line.substring(0, line.indexOf("\""));

                    for (int i = 0; i < 5; i++)
                    {
                        line = reader.readLine();

                        if (line.matches(".*<b>[-A-Za-z\\s]+</b>.*"))
                        {
                            line = line.replaceFirst(".*<b>", "");
                            line = line.replaceFirst("</b>.*", "");

                            name = line;
                            temp.add(name + "," + type + "," + url);

                            break;
                        }
                    }
                }
            }

            reader.close();
        }
        catch (IOException e)
        {
            System.err.println("Unable to read from URL.");
            e.printStackTrace();
        }

        return temp;
    }
}

这是一个奇怪的部分:每次运行时程序都会随机失败。

First run

Second run

Third run

甚至更多:如果您访问这些网页,您会发现他们都拥有&#34;主要内容&#34;在他们的代码中,我的.contains(&#34; MAIN CONTENT&#34;)行应检测到。我在帮助器打印语句中添加了它,以显示它所粘贴的URL以及该行是否存在。每次我使用调试器时,它都会按照我的说法运行。由于成千上万的输入线,我似乎无法通过这一切有效地打破我的方式。我不明白 - 这里肯定有我遗漏的东西。

谢谢大家!

1 个答案:

答案 0 :(得分:2)

您错误地使用ready()方法 - 事实上,您根本不应该使用它。当仍有数据要读取时,它会导致程序停止读取。

readLine()方法就是您所需要的。当您到达文本末尾时,它会返回null 用于控制循环的内容。标准习语是:

String line = null;
while ((line = reader.readLine()) != null) {
    // process the line
}

ready()返回false时,它并不意味着没有任何内容可供阅读,这意味着基础流目前还没有准备好阅读,并且缓冲区中没有字符。换句话说,BufferedReader必须等待 - 可能是几毫秒 - 才能访问更多字符。在我看来,它是一种低级别的方法,甚至不应该具有public可见性。许多人在你之前陷入了这个陷阱。