SSH框架效率问题

背景交代:

现在在做一个毕设,目的从各个招聘网站上(比如智联招聘)爬取职位信息,并存到自己的数据库中。然后进行分析,去重。最后能利用这些数据给用户推荐职位,并绘制一些诸如职位在城市的分布,薪资情况等等的排名的图表出来。

使用的框架:

现在使用到的技术有 SpringMVC + Spring + Hibernate 框架。
分布式采用了比较简单的Hessian。
HTML爬取和分析使用的Jsoup。
数据库MYSql。
前端暂时打算使用Bootstrap 但是还没定是不是自己做,有可能采用修改免费模板的方式。

问题:

图片描述

这是利用以上搭建的环境爬取2940个职位信息的耗时情况。
惨不忍睹。
想问一下在这种架构的情况下如何能提高程序的效率?

以下是爬虫部分的代码:

@Component

public class Spider_ZhiLian implements Runnable{

private WorkDao workDao;

private static Logger logger = Logger.getLogger(Spider_ZhiLian.class);

public Spider_ZhiLian(WorkDao workDao)

{

this.workDao = workDao;

}

public Spider_ZhiLian()

{

}

public void run() {

// TODO Auto-generated method stub

getJobs();

}

public void getJobs()

{

int total = 0;

Calendar a=Calendar.getInstance();

final String YEAR = a.get(Calendar.YEAR)+"-";

List<Work> list = new ArrayList<Work>();

Element errorElements = null;

long startTime = System.currentTimeMillis(); //获取开始时间

long downTime = 0;//下载时间

long thinkTime = 0;//解析时间

long saveTime = 0;//存入数据库时间

for(int t = 0;t<50;t++)

{

list.clear();

try {

long point1start = System.currentTimeMillis(); //下载一个页面的时间

Document document = Jsoup.connect("http://sou.zhaopin.com/jobs/searchresult.ashx?jl=%E9%80%89%E6%8B%A9%E5%9C%B0%E5%8C%BA&isadv=0&sg=91bdb06d4b2c4871a1000b75fe7002b7&p="+t+1).userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31").post();

//System.out.println(document);

long point1end = System.currentTimeMillis(); //下载一个页面的时间

downTime += point1end-point1start;

long point2start = System.currentTimeMillis(); //解析一个页面的时间

Elements companyName = document.select("td.gsmc");//公司

Elements salary = document.select("td.zwyx");//月薪

Elements place = document.select("td.gzdd");//工作地点

Elements name = document.select("td.zwmc");//职位

Elements date = document.select("td.gxsj");//更新时间

Elements infomations = document.select("li.newlist_deatil_two");

//地点:重庆公司性质:股份制企业公司规模:1000-9999人学历:本科

//地点:重庆公司性质:民营公司规模:100-499人学历:不限职位月薪:15001-20000元/月

for(int i = 0;i< companyName.size() ;i++)

{

Work work = new Work();

errorElements = infomations.get(i);

String[] infos = infoSpliter(infomations.get(i).text());

work.setCompanyName(companyName.get(i).text());

work.setName(name.get(i).text());

work.setSalary(salary.get(i).text());

work.setPlace(place.get(i).text());

work.setCompanySize(infos[0]);

work.setDate(Date.valueOf(YEAR+date.get(i).text()));

work.setEducation(infos[1]);

work.setType(2);

work.setUrl(name.get(i).getElementsByTag("a").attr("href"));

total++;

list.add(work);

}

long point2end = System.currentTimeMillis(); //解析一个页面的时间

thinkTime += point2end-point2start;

long point3start = System.currentTimeMillis(); //存入页面的时间

workDao.saveWorkList(list);

long point3end = System.currentTimeMillis(); //存入页面的时间

saveTime += point3end-point3start;

} catch (Exception e) {

e.printStackTrace();

System.out.println(errorElements.text());

}

}

long endTime = System.currentTimeMillis(); //获取开始时间

logger.info("共有 " + total + "个职位,耗时: "+(endTime-startTime)/1000.0 + " 秒。 ");

logger.info("获取HTML耗时 "+downTime/1000.0 + " 秒。 耗时比重: "+ downTime*1.00/(endTime-startTime) *100 + "%");

logger.info("解析HTML耗时 "+thinkTime/1000.0 + " 秒。耗时比重: "+ thinkTime*1.00/(endTime-startTime) *100 + "%");

logger.info("存入数据库耗时 "+saveTime/1000.0 + " 秒。耗时比重: "+ saveTime*1.00/(endTime-startTime) *100 + "%");

logger.info("处理异常耗时 "+(endTime-startTime-saveTime-downTime-thinkTime)/1000.0 + " 秒。耗时比重: "+ (endTime-startTime-saveTime-downTime-thinkTime)*1.00/(endTime-startTime) *100 + "%");

}

//将网站中一串的信息处理成String数组的形式

private String[] infoSpliter(String info)

{

String[] result = new String[2];

String[] temp1 = info.split("公司规模:");

String[] temp2 = null;

if(temp1.length < 2)

{

result[0] = "未知";

}

else

{

temp2 = temp1[1].split("人");

result[0] = temp2[0];//人数(规模)

}

String[] temp3 = info.split("学历:");

String[] temp4 = temp3[1].split("职位月薪:");

result[1] = temp4[0];

return result;

}

}

大家无视我弱智的时间统计方式吧。。。AOP还不太会用。。只能先这么统计一下了。

自己的想法:

图片描述

最左面的电脑(也就是主机)来控制中间三台电脑的爬虫。
中间三台电脑和主机在同一局域网内,三台主机连接互联网爬虫的数据再通过内网传送到主机的数据库上。
我觉得这样的方式应该能提高不少速度。

还有一种想法是在各个爬虫节点上配置数据库,爬虫之后直接存在自己的数据库中,然后主机访问三个爬虫节点的数据库。但是有个问题是数据的重复问题。

最后:

很感谢您能看到这里。
大概就是以上的情况,希望有大神能提出宝贵的建议让我的程序提高些效率。不然这样上百万的数据真的会跑到崩溃。
或者不是效率问题,其他方面有好的建议也欢迎提出。
再次感谢!

回答:

你的耗时分析里已经指出了问题,“获取HTML耗时”占的比重是90%,再看你的代码,业务逻辑是

public void getJobs(){

...

for(int i=0;i<50;i++){

//生成url

//爬取页面

//解析内容

...

}

...

}

并不清楚SSH框架中如何处理这个'''getJobs()'''这个函数,但看起来是单线程的,耗时这么久也就不足为奇了。

所以,应该把下载页面和处理内容两部分的工作分开来。这就是一个生产者-消费者问题了啊:页面下载的功能是生产者,网络IO明显比处理页慢,可以多开几个线程来进行下载页面工作,放入队列里;内容的分析处理部分是消费者,从队列里拿出页面解析就好,看情况要不要多线程。

以上是 SSH框架效率问题 的全部内容, 来源链接: utcz.com/p/170114.html

回到顶部