http://ayang1588.github.io/blog/2013/04/08/catchdata/
最近处于离职状态,正赶清闲,开始着手自己的毕业设计,课题定的是JavaWeb购物平台,打算用SpringMVC+MyBatis实现,打算添加缓存服务器,用什么还没有想好,依赖用Maven管理,数据库用MySql,IDE就用Inetllij IDEA。
购物平台业务都差不多,平时经常使用,业务大家都比较熟悉,我打算模拟当当网,所以昨天直接把数据库设计好,并建了起来,今天打算准备数据,可是product表和book表的字段稍微有点多,如果上网一个一个的摘录,肯定是不行事儿的,也不是coder做的事儿,要准备多的数据,又是重复的事儿,何不让计算机帮你干。所以打算用Java程序抓取现当当网的数据,提取自己想要的,并直接存入数据库。经过一下午的努力基本实现了功能,由于分类并不打算和当当网的分类一样那么多,所以实现了符合自己的半自动化数据抓取功能。可以实现输入当当网的类别(category_path),和起始结束页,自动填充数据库中对应对象。
最开始用的正则匹配抓取内容,后来发现太麻烦了,正则左一斜杠右一斜杠的,又转义又拼接,一会就晕了,所以放弃了,改为像操作Dom树一样进行抓取,用到的开源包Jsoup(文档),也支持像CSS过滤器一样过滤节点,很方便。但是这样并不支持获取js及ajax访问返回数据后的页面,但用htmlunit可以解决这个问题,htmlunit:传说中Java程序员的浏览器,具体使用不太难,就是模拟浏览器,设置好相关属性就可以开始访问了。这里有一篇淘宝关于定向抓取的介绍,大家可以看看(定向抓取漫谈)。
以下是我访问当当数据的类(其余的就不贴了,数据库存储用的最原始的JDBC,没什么好说的,这个只是随便写个大概,够自己用了,其实完全可以拓展成通用的工具类,我就不封装了,本来就挺方便的,直接用也就够了),如果哪里有问题请记得及时给我留言:
1 public class Utils { 2 3 // UrlVo类存放了3个url,列表图片url,详细信息中的图片url,和商品详细信息url 4 // 再通过这三个url可以把所有数据读取出来并封装成对象,然后存入数据库。 5 // 同时将所用到的图片下载到本地。 6 7 /** 8 * 从一个页面获取该页面商品详细信息的url链接和小图片的链接地址 9 * @param url 10 * @return 11 * @throws 12 */ 13 public static void getBookUrlFromPage(String url, List list) throws Exception{ 14 // timeout 0:不断请求 默认:2000毫秒超时 15 Document document = Jsoup.connect(url).timeout(0).get(); 16 Elements node = document.select(".resultlist"); 17 Elements elements = node.get(0).child(0).children(); 18 for (Element item : elements) { 19 UrlVO urlVO = new UrlVO(); 20 urlVO.setProductDetailUrl(item.child(1).child(0).child(0).child(0).attr("href")); 21 urlVO.setSmallImageUrl(item.child(0).child(0).child(0).attr("src")); 22 list.add(urlVO); 23 } 24 } 25 26 /** 27 * 根据url和页数获取商品详细url 28 * @param url 29 * @param startPage 30 * @param endPage 31 * @param list 32 */ 33 public static void getBookUrlByUrlAndPageNum(String url, Integer startPage, Integer endPage, List list) { 34 try { 35 for(int i = startPage; i <= endPage; i++) { 36 String urlStr = url + i; 37 Utils.getBookUrlFromPage(urlStr, list); 38 } 39 } catch (Exception e) { 40 e.printStackTrace(); 41 } 42 } 43 44 /** 45 * 根据商品详细页面获取Product对象 46 * @param url 47 * @return 48 */ 49 public static Product getProductFromUrl(String url) { 50 //这里有些数据利用jsoup获取不到 51 //我用的是htmlunit,设置setJavaScriptEnabled,setAjaxController等参数 52 //具体代码就不贴了,大家可以自己试试 53 //如有需要,求留言 54 return null; 55 } 56 57 /** 58 * 根据图片url和文件名保存图片 59 * @param urlStr 60 * @param filename 61 */ 62 public static void saveImageByUrlAndName(String urlStr, String filename) throws Exception{ 63 // 构造URL 64 URL url = new URL(urlStr); 65 // 打开连接 66 URLConnection con = url.openConnection(); 67 // 输入流 68 InputStream is = con.getInputStream(); 69 // 1K的数据缓冲 70 byte[] bs = new byte[1024]; 71 // 读取到的数据长度 72 int len; 73 // 输出的文件流 74 OutputStream os = new FileOutputStream(filename); 75 // 开始读取 76 while ((len = is.read(bs)) != -1) { 77 os.write(bs, 0, len); 78 } 79 os.flush(); 80 // 关闭连接 81 os.close(); 82 is.close(); 83 } 84 85 // 测试及调用 86 public static void main(String[] args) { 87 List<UrlVO> list = new ArrayList<UrlVO>(); 88 try { 89 getBookUrlByUrlAndPageNum("http://category.dangdang.com/all/?category_path=01.03.38.00.00.00&page_index=", 1, 2, list); 90 // getBookUrlFromPage("http://category.dangdang.com/all/?category_path=01.03.38.00.00.00&page_index=2", list); 91 } catch (Exception e) { 92 e.printStackTrace(); 93 } 94 System.out.println(list.size()); 95 96 // 保存图片 97 // String urlStr = "http://img32.ddimg.cn/28/35/23207212-1_l.jpg"; 98 // try { 99 // saveImageByUrlAndName(urlStr, "1.jpg"); 100 // } catch (Exception e) { 101 // e.printStackTrace(); 102 // } 103 } 104 }