从网页源读取随机失败 - Java
Reading from webpage source randomly fails - Java
这是我在 Java 见过的最奇怪的事情。情况是这样的。我尝试阅读 80 多个 URL 而没有任何类型的 API(这真的很糟糕)。这些网页有一种显示我需要的信息的通用方式,因此我通常可以使用一些正则表达式语句找到感兴趣的项目。
这是我正在尝试阅读的示例网页。 Webpage
我有两个非常草率的 classes 来完成这个:
Tester.java。
这里的 Main 方法只是从我的计算机上读取 URL,并为它们中的每一个调用工具 class 中的一个方法,其中 returns 是一个 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。这是一个充满静态方法的助手 class。这里唯一感兴趣的方法是 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;
}
}
这是奇怪的部分:每次我 运行 程序似乎随机失败。
更奇怪是,如果你访问这些网页,你会发现它们的代码中都有 "MAIN CONTENT",我的 .contains("MAIN CONTENT") 行应该已经检测到。我在辅助打印语句中添加了显示卡住的 URL 并且该行存在的内容。每次我使用调试器时,它都会按照我的要求工作。由于有数千行输入,我似乎无法有效地断点我的方式。我不明白 - 一定有我在这里遗漏的东西。
谢谢大家!
您错误地使用了 ready()
方法——事实上,您根本不应该使用它。它导致您的程序在仍有数据要读取时停止读取。
readLine()
方法就是您所需要的。当你到达文本的末尾时,它 returns null
和 这就是你用来控制循环的 。标准成语是:
String line = null;
while ((line = reader.readLine()) != null) {
// process the line
}
当ready()
returns false
时,这并不意味着没有什么可读的,这意味着底层流目前还没有准备好读取,并且有其缓冲区中没有字符。换句话说,BufferedReader 必须等待——可能是几毫秒——才能访问更多字符。在我看来,这是一种 low-level 方法,甚至不应该具有 public
可见性。许多人在你之前掉进了这个陷阱。
这是我在 Java 见过的最奇怪的事情。情况是这样的。我尝试阅读 80 多个 URL 而没有任何类型的 API(这真的很糟糕)。这些网页有一种显示我需要的信息的通用方式,因此我通常可以使用一些正则表达式语句找到感兴趣的项目。
这是我正在尝试阅读的示例网页。 Webpage
我有两个非常草率的 classes 来完成这个:
Tester.java。 这里的 Main 方法只是从我的计算机上读取 URL,并为它们中的每一个调用工具 class 中的一个方法,其中 returns 是一个 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。这是一个充满静态方法的助手 class。这里唯一感兴趣的方法是 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;
}
}
这是奇怪的部分:每次我 运行 程序似乎随机失败。
更奇怪是,如果你访问这些网页,你会发现它们的代码中都有 "MAIN CONTENT",我的 .contains("MAIN CONTENT") 行应该已经检测到。我在辅助打印语句中添加了显示卡住的 URL 并且该行存在的内容。每次我使用调试器时,它都会按照我的要求工作。由于有数千行输入,我似乎无法有效地断点我的方式。我不明白 - 一定有我在这里遗漏的东西。
谢谢大家!
您错误地使用了 ready()
方法——事实上,您根本不应该使用它。它导致您的程序在仍有数据要读取时停止读取。
readLine()
方法就是您所需要的。当你到达文本的末尾时,它 returns null
和 这就是你用来控制循环的 。标准成语是:
String line = null;
while ((line = reader.readLine()) != null) {
// process the line
}
当ready()
returns false
时,这并不意味着没有什么可读的,这意味着底层流目前还没有准备好读取,并且有其缓冲区中没有字符。换句话说,BufferedReader 必须等待——可能是几毫秒——才能访问更多字符。在我看来,这是一种 low-level 方法,甚至不应该具有 public
可见性。许多人在你之前掉进了这个陷阱。