我编写了一个控制器,它将域名作为输入,抓取整个站点并以JSON格式返回结果
http://crawlmysite-tgugnani.rhcloud.com/getUrlCrawlData/www.google.com
这会提供数据谷歌
http://crawlmysite-tgugnani.rhcloud.com/getUrlCrawlData/www.yahoo.com
这为雅虎提供了数据
如果我尝试同时运行这两个URL,我会看到我正在获取混合数据,并且其中一个的结果正在影响另一个,即使我尝试从不同的计算机中搜索它们。
这是我的控制器
@RequestMapping("/getUrlCrawlData/{domain:.+}")
@ResponseBody
public String registerContact(@PathVariable("domain") String domain) throws HttpStatusException, SQLException, IOException {
List<URLdata> urldata = null;
Gson gson = new Gson();
String json;
urldata = crawlService.crawlURL("http://"+domain);
json = gson.toJson(urldata);
return json;
}
我需要做什么修改以允许多个独立连接。
更新
以下是我的抓取服务
public List<URLdata> crawlURL(String domain) throws HttpStatusException, SQLException, IOException{
testDomain = domain;
urlList.clear();
urlMap.clear();
urldata.clear();
urlList.add(testDomain);
processPage(testDomain);
//Get all pages
for(int i = 1; i < urlList.size(); i++){
if(urlList.size()>=500){
break;
}
processPage(urlList.get(i));
//System.out.println(urlList.get(i));
}
//Calculate Time
for(int i = 0; i < urlList.size(); i++){
getTitleAndMeta(urlList.get(i));
}
return urldata;
}
public static void processPage(String URL) throws SQLException, IOException, HttpStatusException{
//get useful information
try{
Connection.Response response = Jsoup.connect(URL)
.userAgent("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.21 (KHTML, like Gecko) Chrome/19.0.1042.0 Safari/535.21")
.timeout(10000)
.execute();
Document doc = response.parse();
//get all links and recursively call the processPage method
Elements questions = doc.select("a[href]");
for(Element link: questions){
String linkName = link.attr("abs:href");
if(linkName.contains(testDomain.replaceAll("http://www.", ""))){
if(linkName.contains("#")){
linkName = linkName.substring(0, linkName.indexOf("#"));
}
if(linkName.contains("?")){
linkName = linkName.substring(0, linkName.indexOf("?"));
}
if(!urlList.contains(linkName) && urlList.size() <= 500){
urlList.add(linkName);
}
}
}
}
catch(HttpStatusException e){
System.out.println(e);
}
catch(SocketTimeoutException e){
System.out.println(e);
}
catch(UnsupportedMimeTypeException e){
System.out.println(e);
}
catch(UnknownHostException e){
System.out.println(e);
}
catch(MalformedURLException e){
System.out.println(e);
}
}
答案 0 :(得分:2)
您的每个请求(http://crawlmysite-tgugnani.rhcloud.com/getUrlCrawlData/www.google.com和http://crawlmysite-tgugnani.rhcloud.com/getUrlCrawlData/www.yahoo.com)都在一个单独的线程中处理。您有两个crawlURL()
方法实例同时工作,但两种方法都使用相同的变量(testDomain
,urlList
,urlMap
和urldata
)。所以他们把这些变量中的数据搞得一团糟。
解决问题的一种方法是在本地(在方法内)声明这些变量。这样,将为crawlURL()
的每次调用创建这些变量的新实例。或者,您可以为CrawlService
方法的每次调用创建crawlURL()
类的新实例。
同步线程在这里是一个坏主意,因为一个请求将等待另一个请求完成,然后由crawlURL()
处理。
答案 1 :(得分:1)
就SpringMVC而言,每个请求都在单独的线程中运行。所以我认为问题出现在crawlService
中,我认为,这不是无国籍的(像单身一样)。尝试为每个请求创建新的抓取服务,并检查您的数据是否未混合。如果创建爬网服务是昂贵的操作,您应该重写它以无状态方式工作。
@RequestMapping("/getUrlCrawlData/{domain:.+}")
@ResponseBody
public String registerContact(@PathVariable("domain") String domain) throws HttpStatusException, SQLException, IOException {
Gson gson = new Gson();
List<URLdata> = new CrawlService().crawlURL("http://"+domain);
return gson.toJson(urldata);
}
答案 2 :(得分:0)
我认为
urldata = crawlService.crawlURL("http://"+domain);
此crawl Service
来电是同时受Multiple requests
影响的电话。
检查crawlService
是否安全multithreading
。
即检查crawlURL()
方法是synchronized
,如果不是synchronized
。
synchronize the block
内调用crawlservice
的或controller
。