我已经编写了一些代码来梳理网站上大约10000个网页,以便在网站上整理用户人口统计信息。该程序的基础是读取网站源代码的每一行,解析出所需的数据,然后转到下一页。
我遇到的问题是大约在第650页左右,程序从每秒3页读取到每10-15秒1页。它总是发生在程序执行的同一点。我开始想知道这可能是我的程序的内存问题,并开始检查它的每个方面。最终我把程序剥离了它的基础:
步骤1)创建一个URL对象数组。
步骤2)循环遍历数组并打开/关闭缓冲读取器以读取每一行。
步骤3)阅读整个页面并转到下一行。
即使这在确切的位置放慢了速度,所以这对我正在解析的数据或我存储的数据不是问题。这是以某种方式循环的结果。我想知道我写的内容是否存在导致问题的内存问题?否则,我唯一的猜测就是以某种方式我对网站服务器打电话太快,故意让我放慢速度。
**显然不是最好的书面代码,因为我是新手,并且受到一堆草率编码的影响。但它确实完美地执行了我想要的。问题是它在大约十分钟后变慢到爬行速度,这将无法正常工作。
以下是相关代码:
数组代码
import java.io.IOException;
import java.net.URL;
public class UrlArrayBuild {
private int page_count; //number of pages
public URL[] urlArray; //array of webpage url's
public UrlArrayBuild(int page) { //object constructor
page_count = page; //initializes page_count
urlArray = new URL[page_count]; //initializes page_count
}
protected void buildArray() throws IOException { // method assigns strings to UrlArray object
int count; //counter for iteration
for(int i = 0; i < page_count; i++) { //loops through
count = i * 60; //sets user number at end of page
URL website = new URL("http://...." + count);
urlArray[i] = website; //url address
//System.out.println(urlArray[i]); //debug
}
}
protected URL returnArrayValue(int index) { //method returns string value in array of given index
//System.out.println(urlArray[index]); //debug
return urlArray[index];
}
protected int returnArrayLength() { //method returns length of array
//System.out.println(urlArray.length); //debug
return urlArray.length;
}
}
读者代码
import java.net.*;
import java.io.*;
public class DataReader {
public static void main(String[] args) throws IOException {
UrlArrayBuild PrimaryArray = new UrlArrayBuild(9642); //Creates array object
PrimaryArray.buildArray(); //Builds array
//Create and initialize variables to use in loop
URL website = null;
String inputLine = null;
//Loops through array and reads source code
for (int i = 0; i < PrimaryArray.returnArrayLength(); i++) {
try {
website = PrimaryArray.returnArrayValue(i); //acquires url
BufferedReader inputStream = new BufferedReader(new InputStreamReader(website.openStream())); //reads url source code
System.out.println(PrimaryArray.returnArrayValue(i)); //prints out website url. I use it as a check to monitor progress
while((inputLine = inputStream.readLine()) != null) {
if (inputLine.isEmpty()) { //checks for blank lines
continue;
} else {
//begin parsing code. This is currently commented so there is nothing that occurs here
}
}
inputStream.close();
} finally {
//extraneous code here currently commented out.
}
}
}
答案 0 :(得分:0)
某些延迟会导致网站出现问题,特别是如果它们内容丰富的话。这可能是一个原因。 解析也可能是一些延迟的因素。因此,我个人建议使用有用的库进行解析,这可能会更好地进行优化。 祝你好运!
答案 1 :(得分:0)
这两个相关的解决方案都有很多工作,但遗憾的是,需要一个复杂的解决方案来解决您的问题。基本上,存在异步框架来解决这个问题。
答案 2 :(得分:0)
我认为在循环遍历数组时,您可以使用多线程技术和异步java方法调用来提高性能。
答案 3 :(得分:0)
您的代码没有明显的错误可以解释这一点。当然不在你向我们展示的代码中。您的代码不会保存正在读取的任何内容,因此无法以这种方式泄漏内存。它不应泄漏资源...因为如果有任何I / O异常,应用程序会立即终止。
(但是,如果您的代码在I / O异常后尝试继续,那么您需要将close()
调用移动到finally
块以避免套接字/文件描述符泄漏。)
很可能是服务器端或(可能)网络问题:
查看650页标记附近的页面是否有异常。它们更大吗?它们是否需要额外的服务器端处理(意味着它们的交付速度会更慢)?
查看服务器端负载(应用程序运行时)及其日志文件。
检查是否已实施某种服务器请求限制;例如作为反DoS措施。
检查是否已实施某种网络流量限制。
还要检查客户端资源使用情况。我希望CPU使用率保持不变,或者在650页标记处尾随。如果CPU使用量增加,则会将怀疑重新带回应用程序。