爬虫其实就是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本,有了爬虫这个技术,可以大大提高工作效率,那java怎么写爬虫代码?下面来我们就用实例给大家讲解一下。
如下图,我要获取京东上的图书的价格,和图书名,还有图书的id(id是唯一标识,可作为数据表的主键)
model
用来封装对象,我要抓取一本书的数据包括,书籍的id,书名及价格。ecliplse中生成set、get方法的快捷键是shift+alt+s然后选择生成setter、getter
package model; public class JdModel { private String bookID; private String bookName; private String bookPrice; public String getBookID() { return bookID; } public void setBookID(String bookID) { this.bookID = bookID; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public String getBookPrice() { return bookPrice; } public void setBookPrice(String bookPrice) { this.bookPrice = bookPrice; } }
main
主方法,尽量要求简单,这里我就这样写了。这里面有注释,很好理解。
package main; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.client.HttpClient; import org.apache.http.impl.client.DefaultHttpClient; import db.MYSQLControl; import model.JdModel; import util.URLFecter; public class JdongMain { //log4j的是使用,不会的请看之前写的文章 static final Log logger = LogFactory.getLog(JdongMain.class); public static void main(String[] args) throws Exception { //初始化一个httpclient HttpClient client = new DefaultHttpClient(); //我们要爬取的一个地址,这里可以从数据库中抽取数据,然后利用循环,可以爬取一个URL队列 String url = "http://search.jd.com/Search?keyword=Python&enc=utf-8&book=y&wq=Python&pvid=33xo9lni.p4a1qb"; //抓取的数据 List < JdModel > bookdatas = URLFecter.URLParser(client, url); //循环输出抓取的数据 for (JdModel jd: bookdatas) { logger.info("bookID:" + jd.getBookID() + "\t" + "bookPrice:" + jd.getBookPrice() + "\t" + "bookName:" + jd.getBookName()); } //将抓取的数据插入数据库 MYSQLControl.executeInsert(bookdatas); } }
util
util中包含两个文件,URLFecter 与HTTPUtils,其中URLFecter 调用了HTTPUtils类。
package util; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.util.EntityUtils; import model.JdModel; import parse.JdParse; public class URLFecter { public static List < JdModel > URLParser(HttpClient client, String url) throws Exception { //用来接收解析的数据 List < JdModel > JingdongData = new ArrayList < JdModel > (); //获取网站响应的html,这里调用了HTTPUtils类 HttpResponse response = HTTPUtils.getRawHtml(client, url); //获取响应状态码 int StatusCode = response.getStatusLine() .getStatusCode(); //如果状态响应码为200,则获取html实体内容或者json文件 if (StatusCode == 200) { String entity = EntityUtils.toString(response.getEntity(), "utf-8"); JingdongData = JdParse.getData(entity); EntityUtils.consume(response.getEntity()); } else { //否则,消耗掉实体 EntityUtils.consume(response.getEntity()); } return JingdongData; } }
上面程序调用的HTTPUtils这个类,以下是HTTPUtils这个类。
package util; import java.io.IOException; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.message.BasicHttpResponse; public abstract class HTTPUtils { public static HttpResponse getRawHtml(HttpClient client, String personalUrl) { //获取响应文件,即html,采用get方法获取响应数据 HttpGet getMethod = new HttpGet(personalUrl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1 , HttpStatus.SC_OK, "OK"); try { //执行get方法 response = client.execute(getMethod); } catch (IOException e) { e.printStackTrace(); } finally { // getMethod.abort(); } return response; } }
parse
parse主要是通过Jsoup来解析html文件。并将解析后的数据,封装在List集合中,将数据通过层层返回到main方法中。
package parse; import java.util.ArrayList; import java.util.List; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import model.JdModel; /* * 用于将上面传下来的html解析,获取我们需要的内容 * 解析方式,采用Jsoup解析,有不明白Jsoup的可以上网搜索API文档 * Jsoup是一款很简单的html解析器 */ public class JdParse { public static List < JdModel > getData(String html) throws Exception { //获取的数据,存放在集合中 List < JdModel > data = new ArrayList < JdModel > (); //采用Jsoup解析 Document doc = Jsoup.parse(html); //获取html标签中的内容 Elements elements = doc.select("ul[class=gl-warp clearfix]") .select("li[class=gl-item]"); for (Element ele: elements) { String bookID = ele.attr("data-sku"); String bookPrice = ele.select("div[class=p-price]") .select("strong") .select("i") .text(); String bookName = ele.select("div[class=p-name]") .select("em") .text(); //创建一个对象,这里可以看出,使用Model的优势,直接进行封装 JdModel jdModel = new JdModel(); //对象的值 jdModel.setBookID(bookID); jdModel.setBookName(bookName); jdModel.setBookPrice(bookPrice); //将每一个对象的值,保存到List集合中 data.add(jdModel); } //返回数据 return data; } }
db
db中包含两个java文件,MyDataSource,MYSQLControl。这两个文件的作用已在前面说明了。
package db; import javax.sql.DataSource; import org.apache.commons.dbcp2.BasicDataSource; public class MyDataSource { public static DataSource getDataSource(String connectURI) { BasicDataSource ds = new BasicDataSource(); //MySQL的jdbc驱动 ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUsername("root"); //所要连接的数据库名 ds.setPassword("112233"); //MySQL的登陆密码 ds.setUrl(connectURI); return ds; } }
下面是MYSQLControl,主要使用QueryRunner方法操作数据库,使用时是batch方法。
package db; import java.sql.SQLException; import java.util.List; import javax.sql.DataSource; import org.apache.commons.dbutils.QueryRunner; import model.JdModel; /* * Mysql操作的QueryRunner方法 * 一个数据库操作类,别的程序直接调用即可 */ public class MYSQLControl { //根据自己的数据库地址修改 static DataSource ds = MyDataSource.getDataSource("jdbc:mysql://127.0.0.1:3306/moviedata"); static QueryRunner qr = new QueryRunner(ds); //第一类方法 public static void executeUpdate(String sql) { try { qr.update(sql); } catch (SQLException e) { e.printStackTrace(); } } //第二类数据库操作方法 public static void executeInsert(List < JdModel > jingdongdata) throws SQLException { /* * 定义一个Object数组,行列 * 3表示列数,根据自己的数据定义这里面的数字 * params[i][0]等是对数组赋值,这里用到集合的get方法 * */ Object[][] params = new Object[jingdongdata.size()][3]; for (int i = 0; i < params.length; i++) { params[i][0] = jingdongdata.get(i) .getBookID(); params[i][1] = jingdongdata.get(i) .getBookName(); params[i][2] = jingdongdata.get(i) .getBookPrice(); } qr.batch("insert into jingdongbook (bookID, bookName, bookPrice)" + "values (?,?,?)", params); System.out.println("执行数据库完毕!" + "成功插入数据:" + jingdongdata.size() + "条"); } }
再看main方法
在main方法中有这样一句程序,这便是调用了操作数据库MYSQLControl程序,将抓取的数据插入到数据库中了
MYSQLControl.executeInsert(bookdatas);
爬虫效果展示
到此,便完成了这个简单网络爬虫的编程工作,下面来看看程序运行的结果吧。
数据库中的结果如下:
这样就完成了java开发爬虫的代码,其实写网络爬虫,一定要有逻辑顺序,将逻辑理清了,才能将爬虫代码写好!最后大家如果想要了解更多java实例知识,敬请关注奇Q工具网。
推荐阅读: