首页 > 代码库 > 简单的java采集程序二

简单的java采集程序二

继【简单的java采集程序】,这里将完成对整个网站的号码段的采集任务。

【使用预编译+批处理采集网页内容至数据库表中】

 

       在之前我们用statement类来创建sql语句的执行对象,以实现插入字段到数据库的操作,但由于插入的数据量较大,如果继续用statement操作话,会很耗时间,我们用其子类PreparedStatement来进行操作。

     PreparedStatement 可以实现sql语句的预编译,我们只需要通过其setString()方法传参即可,这样不仅效率提高了,而且也会更加安全,可防止SQL注入。推荐相关文章

 

     另外我们还可以调用其addBatch()方法 和 executeBatch()实现批量插入处理。

代码如下,喜欢把数据库链接作为一个单独的类

import java.sql.DriverManager;import java.sql.SQLException;import com.mysql.jdbc.Connection;public class database {	public static String driver ="com.mysql.jdbc.Driver";		public static String url="jdbc:mysql://127.0.0.1:3306/tele_dat?autoReconnect=true&characterEncoding=UTF-8";	public static String user   ="root";	public static String password = "123456";	public static java.sql.Connection conn = null;		//返回一个数据库连接对象	public static  Connection  ConnectToDataBase(){		try {			Class.forName(driver);		} catch (ClassNotFoundException e) {			System.out.println("加载驱动失败");			e.printStackTrace();		}				try {			conn = DriverManager.getConnection(url, user, password);			System.out.println("连接成功");		} catch (SQLException e) {			System.out.println("连接出问题了");			e.printStackTrace();		}		return (Connection) conn;		}			//测试连接数据库	public static void main(String args[])	{		database.ConnectToDataBase();		}}

主体程序

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.URL;import java.sql.Connection;import java.sql.PreparedStatement;import java.util.regex.Matcher;import java.util.regex.Pattern;public class Crawl {	private static Connection conn = database.ConnectToDataBase();      static String home_url = "http://www.hiphop8.com";   //网站首页        static String pattern_pro_city = "<DIV class=title><SPAN>(.*?) - (.*?)<\\/SPAN><\\/DIV>";   //匹配省名,市名 	static String pattern_number = ">(13\\d{5}|15\\d{5}|18\\d{5}|147\\d{4})<";  //匹配号码段 	static String pattern_pro ="\\w{3}\\.\\w{7}\\.\\w{3}\\/\\w{4}\\/\\w+";   //省份URL	static String pattern_city_hz="<LI><A href=http://www.mamicode.com/"(.*?)\" target=_blank>";    //城市URL的后缀>

      实际运行程序,发现有500多个重复的号码段,因为襄樊市 改成 襄阳市,这两个市的号码段全部一样,而数据库表中是以segment(号码)作为主键,所以要设置,当插入有相同主键的sql语句时,自动忽略跳过,方法就是在insert 后面加上ignore就可以了。

      另外设置id为auto_increment,但如果把数据表里的数据清空之后,id不会从1重新开始,这时只要在mysql命令行下输入 truncate table table_name 就可以实现id从1开始了。

运行结果截图image

 

     显然,6分钟的速度还是太慢了,后面试了几次都是在6~8分钟之内(不过相对于不用批处理而直接用statement已经快很多了)。因此还得想办法优化。

【使用智能批量处理+StringBuilder的append()方法】

        在插入mysql数据库表中时,可以以insert ignore into number_segment(segment,province,city) values(?, ?, ?),vaulues(?),values(?,?,?)…的形式进行批量插入,上面使用setString()方法传参还是太慢了,直接用StringBuilder的append()方法吧,我们都知道appedn()方法进行字符串相加处理的效率是很高的,所以我们每次在insert语句后面加入一段“vaulues(?,?,?),”这样形式的字符串,然后批处理插入,这里通过变量all_tele_num进行批量处理的的控制,我们规定每次批量执行2000个数据段插入。

       直接看代码吧

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.URL;import java.sql.Connection;import java.sql.PreparedStatement;import java.util.regex.Matcher;import java.util.regex.Pattern;public class SecondCrawl {	private static Connection conn = database.ConnectToDataBase();		//预编译 + StringBuilder	static StringBuilder PreStat = new StringBuilder();	 	static String Qz = "insert ignore into number_segment(segment,province,city) values"; 	static String insertSQL = "insert ignore into number_segment(segment,province,city) values(?, ?, ?)";    static int len1 = Qz.length();    static PreparedStatement pst = null;    static String home_url = "http://www.hiphop8.com";        static String pattern_pro_city = "<DIV class=title><SPAN>(.*?) - (.*?)<\\/SPAN><\\/DIV>";   //匹配省名,市名 	static String pattern_number = ">(13\\d{5}|15\\d{5}|18\\d{5}|147\\d{4})<";  //匹配号码段 	static String pattern_pro ="\\w{3}\\.\\w{7}\\.\\w{3}\\/\\w{4}\\/\\w+";   //省份URL	static String pattern_city_hz="<LI><A href=http://www.mamicode.com/"(.*?)\" target=_blank>";    //城市URL的后缀>

运行截图030641D5CD414D92B15219D95CAFC302

 

        测试了几次,运行时间是在2分钟左右,又提速了不少,不过还是有很大的提升空间的,因为自己在测试时,如果程序仅仅是插入20多万的sql语句,可以在几秒钟内完成。

      说道再优化,自己的思路是把网站url采集和插入数据库使用多线程进行并发操作,现在正在学习java的多线程,也在尝试用多线程的方法写采集程序,如果大家还有更好的方法,也可以给我留言,愿意和大家一起交流进步。

简单的java采集程序二