节前一个误操作把mysql中record表和movie表都清空了,显然我是没有做什么mysql备份的。所以,索性我把所有的表数据都清空的,一夜回到解放前……
项目地址:https://github.com/DMinerJackie/JewelCrawler
在上一个版本中,record表存储了7万多条记录,爬取的有4万多条,但是可以明显的发现爬取的数据量越多的时候,机子就越卡。又一次报错,是有关JDBC的,还有一次机子跑卡死了。
仔细一琢磨,上个版本的爬虫程序与数据库的读写次数太频繁,存在以下问题:
1.程序运行,从种子地址开始,对于每次爬取的网站地址先查询数据库是否存在该条记录,如果不存在,则立即插入;
2.当前网站地址爬取完毕后,查找数据库从中取出第一个crawled为0的记录进行爬取,每次只取一条;
3.存储电影详情页记录以及短评数据都是采用解析一条则立即存储到数据库。
显然,上面的这种方式是一目了然的效率低下,所以今天下午对相关代码进行改造,部分实现了批量插入,尽可能减少与数据库的交互,从而降低时空成本。
在git clone完项目后,发现一个很诡异的现象,JewelCrawler每次都是爬取种子地址,并没有一次查询数据库中crawled字段为0的记录进行一一爬取,但是之前在本机上是完美运行的,可能是在push代码前做了改动影响运行了。
既然问题出现了,就顺着这个版本看看,最终发现问题的原因是对于种子网址并没有存储到mysql的record表中,所以在DoubanCrawler类中
//set boolean value "crawled" to true after crawling this page
sql = "UPDATE record SET crawled = 1 WHERE URL = '" + url + "'";
stmt = conn.createStatement();
if (stmt.executeUpdate(sql) > 0) {
//get the next page that has not been crawled yet
sql = "SELECT * FROM record WHERE crawled = 0";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
if (rs.next()) {
url = rs.getString(2);
} else {
//stop crawling if reach the bottom of the list
break;
}
//set a limit of crawling count
if (count > Constants.maxCycle || url == null) {
break;
}
}
执行stmt.executeUpdate(sql) > 0是返回的值为0,从而不会从数据库中读取crawled为0的记录,最后就一直在while的循环中爬取种子网站。