Jsp编程

 JAVA综合面试题:页面的抓取、解析、保存数据库和生成HTML的页面展示 收藏
次例子可以用来学习网络编程,正则表达式的使用,泛型,数据库的基本操作等JAVA知识

 


问题如下:来源于论坛

http://topic.csdn.net/u/20090616/13/59aa4e2d-3752-45df-9c1b-c65c46c3e4d7.html

 


写一个jsp页面,访问时显示从下面的页面提取出的销售商详细信息:价格、运费、经销
商基本信息等,并写到一个数据库表里。
http://www.amazon.com/gp/offer-listing/B0012J52OC/

 

 

数据抓取的问题,涉及到
1 用URLConnection 读取页面信息,用httpclient也行
2 用Pattern 解析页面并拿到你要的信息
3 显示数据
4 存入数据库

这个是一个综合的考试,涉及的知识面比较广。

1 我这里只给出关键的部分,使用java程序实现,而不是JSP的代码。移植工作请自行完成。
2 我使用自己的数据库连接,请替换为应用服务器提供的数据源为好
3 代码分三部分,数据库结构,POJO类和应用程序,当然还有一个辅助类,也是我自己写的

4 欢迎光临老紫竹的JAVA世纪网 http://www.java2000.net, 呵呵,广告放里面了

一、数据库结构 AmazonGoods.sql 使用的是MySQL的数据库

view plaincopy to clipboardprint?
-- ----------------------------  
-- Table structure for amazongoods  
-- ----------------------------  
CREATE TABLE `amazongoods` (  
  `id` int(11) NOT NULL AUTO_INCREMENT,  
  `price` decimal(10,0) NOT NULL,  
  `shipping` decimal(10,0) NOT NULL,  
  `Seller` text NOT NULL,  
  PRIMARY KEY (`id`)  
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; 
-- ----------------------------
-- Table structure for amazongoods
-- ----------------------------
CREATE TABLE `amazongoods` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `price` decimal(10,0) NOT NULL,
  `shipping` decimal(10,0) NOT NULL,
  `Seller` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
 


二、POJO类 AmazonGoods.java

view plaincopy to clipboardprint?
package com.laozizhu.test.amazon;  
import java.math.BigDecimal;  
/** 
 * 某一行的商品数据 
 *  
 * @author 老紫竹的家(laozizhu.com) 
 *  
 */ 
class AmazonGoods {  
  public long getId() {  
    return id;  
  }  
  public void setId(long id) {  
    this.id = id;  
  }  
  public BigDecimal getPrice() {  
    return price;  
  }  
  public void setPrice(BigDecimal price) {  
    this.price = price;  
  }  
  public BigDecimal getShipping() {  
    return shipping;  
  }  
  public void setShipping(BigDecimal shipping) {  
    this.shipping = shipping;  
  }  
  public String getSeller() {  
    return seller;  
  }  
  public void setSeller(String seller) {  
    this.seller = seller;  
  }  
  // 序列号,主键  
  private long id;  
  // 价格  
  private BigDecimal price;  
  // 运费  
  private BigDecimal shipping;  
  // 商家信息  
  private String seller;  

package com.laozizhu.test.amazon;
import java.math.BigDecimal;
/**
 * 某一行的商品数据
 *
 * @author 老紫竹的家(laozizhu.com)
 *
 */
class AmazonGoods {
  public long getId() {
    return id;
  }
  public void setId(long id) {
    this.id = id;
  }
  public BigDecimal getPrice() {
    return price;
  }
  public void setPrice(BigDecimal price) {
    this.price = price;
  }
  public BigDecimal getShipping() {
    return shipping;
  }
  public void setShipping(BigDecimal shipping) {
    this.shipping = shipping;
  }
  public String getSeller() {
    return seller;
  }
  public void setSeller(String seller) {
    this.seller = seller;
  }
  // 序列号,主键
  private long id;
  // 价格
  private BigDecimal price;
  // 运费
  private BigDecimal shipping;
  // 商家信息
  private String seller;
}


三、应用类

view plaincopy to clipboardprint?
package com.laozizhu.test.amazon;  
import java.math.BigDecimal;  
import java.sql.Connection;  
import java.sql.DriverManager;  
import java.sql.PreparedStatement;  
import java.util.ArrayList;  
import java.util.List;  
import java.util.Properties;  
import java.util.regex.Matcher;  
import java.util.regex.Pattern;  
import com.laozizhu.tools.PageService;  
public class AmazonFetch {  
  /** 
   * @param args 
   */ 
  public static void main(String[] args) {  
    // 我这里需要设置代理,如果你能直接访问互联网,则无需这段代码了  
    initProxy();  
    // 读取页面数据  
    String str = PageService.getPage("http://www.amazon.com/gp/offer-listing/B0012J52OC/", "ISO-8859-1");  
    // 解析页面,拿到商品信息  
    List<AmazonGoods> list = parse(str);  
    // 生成HTML表格  
    buildTable(list);  
    // 存入数据库  
    saveToMySQL(list);  
  }  
  /** 
   * 简单的代理服务器,无需密码认证 
   */ 
  private static void initProxy() {  
    Properties prop = System.getProperties();  
    // prop.put("proxySet", "true");  
    // 设置http访问要使用的代理服务器的地址  
    prop.setProperty("http.proxyHost", "10.60.8.20");  
    // 设置http访问要使用的代理服务器的端口  
    prop.setProperty("http.proxyPort", "8080");  
  }  
  // 注意,美元符号要转义  
  // 因为报价都包含小数点,所以用数字+小数点+2位小数即可  
  // 商家信息包含了对应的标签  
  static Pattern pPrice = Pattern.compile(  
      "<span class=/"price/">//$([//d]+//.[//d]{2})</span>.*?(<ul class=/"sellerInformation/">.+?</ul>)", Pattern.DOTALL);  
  // 运费  
  // <span class="price_shipping">+ $6.04</span>  
  static Pattern pShipping = Pattern  
      .compile("<span class=/"price_shipping/">//+ //$([//d]+//.[//d]{2})</span>", Pattern.DOTALL);  
  /** 
   * 解析页面,获得商品列表 
   *  
   * @param page 
   *          页面 
   * @return 商品列表 
   */ 
  private static List<AmazonGoods> parse(String page) {  
    // 首先,把商品分成多个字符串片段  
    // 分割符就是表格里的内容了。这个得查看HTML源代码才能找到合适的  
    String[] strs = page.split("<tbody class=/"result/">");  
    // 构造结果  
    // 默认长度为片段的长度,呵呵  
    List<AmazonGoods> list = new ArrayList<AmazonGoods>(strs.length);  
    AmazonGoods goods = null;  
    // 循环解析每个商品片段  
    for (String str : strs) {  
      // 注意,不是每个商品都有运费,所以正则最好不要写一个  
      // 当然,你愿意弄复杂了也行,我个人不推荐这么做  
      Matcher m = pPrice.matcher(str);  
      if (m.find()) {  
        goods = new AmazonGoods();  
        goods.setPrice(new BigDecimal(m.group(1)));  
        // 这里面包含了HTML的信息,包括Javascript内容,不过比较难删除  
        // 因为有些页面文字是用js显示的,还是保留的比较好  
        goods.setSeller(m.group(2));  
        // 查找运费  
        m = pShipping.matcher(str);  
        if (m.find()) {  
          goods.setShipping(new BigDecimal(m.group(1)));  
        }  
        // 将商品加入列表  
        list.add(goods);  
      } else {  
        // 没有找到价格,则这部分不包含商品信息,无需继续  
        continue;  
      }  
    }  
    return list;  
  }  
  private static String buildTable(List<AmazonGoods> list) {  
    StringBuilder b = new StringBuilder("<table>");  
    b.append("<tr><th>价格</th><th>运费</th><th>商家信息</th></tr>");  
    for (AmazonGoods goods : list) {  
      b.append("<tr><th>" + goods.getPrice() + "</th><th>" + goods.getShipping() + "</th><th>" + goods.getSeller()  
          + "</th></tr>");  
    }  
    b.append("</table>");  
    return b.toString();  
  }  
  private static void saveToMySQL(List<AmazonGoods> list) {  
    // 这里就用最原始的方法获得数据库连接了。  
    // 数据库结构请参考AmazonGoods.sql  
    // 使用test的数据库  
    Connection con = null;  
    PreparedStatement st = null;  
    String url = "jdbc:mysql://localhost:3306/";  
    String db = "test";  
    String driver = "com.mysql.jdbc.Driver";  
    String user = "test";  
    String pass = "test";  
    BigDecimal ZERO = new BigDecimal("0");  
    try {  
      Class.forName(driver);  
      con = DriverManager.getConnection(url + db, user, pass);  
      st = con.prepareStatement("insert into AmazonGoods (price,shipping,seller) values(?,?,?)");  
      for (AmazonGoods goods : list) {  
        st.setBigDecimal(1, goods.getPrice());  
        st.setBigDecimal(2, goods.getShipping()==null?ZERO:goods.getShipping());  
        st.setString(3, goods.getSeller());  
        if (st.executeUpdate() <= 0) {  
          throw new Exception("保存数据错误!");  
        }  
        st.clearParameters();  
      }  
    } catch (Exception ex) {  
      ex.printStackTrace();  
    } finally {  
      if (st != null) {  
        try {  
          st.close();  
        } catch (Exception ex) {  
        }  
      }  
      if (con != null) {  
        try {  
          con.close();  
        } catch (Exception ex) {  
        }  
      }  
    }  
  }  

package com.laozizhu.test.amazon;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.laozizhu.tools.PageService;
public class AmazonFetch {
  /**
   * @param args
   */
  public static void main(String[] args) {
    // 我这里需要设置代理,如果你能直接访问互联网,则无需这段代码了
    initProxy();
    // 读取页面数据
    String str = PageService.getPage("http://www.amazon.com/gp/offer-listing/B0012J52OC/", "ISO-8859-1");
    // 解析页面,拿到商品信息
    List<AmazonGoods> list = parse(str);
    // 生成HTML表格
    buildTable(list);
    // 存入数据库
    saveToMySQL(list);
  }
  /**
   * 简单的代理服务器,无需密码认证
   */
  private static void initProxy() {
    Properties prop = System.getProperties();
    // prop.put("proxySet", "true");
    // 设置http访问要使用的代理服务器的地址
    prop.setProperty("http.proxyHost", "10.60.8.20");
    // 设置http访问要使用的代理服务器的端口
    prop.setProperty("http.proxyPort", "8080");
  }
  // 注意,美元符号要转义
  // 因为报价都包含小数点,所以用数字+小数点+2位小数即可
  // 商家信息包含了对应的标签
  static Pattern pPrice = Pattern.compile(
      "<span class=/"price/">//$([//d]+//.[//d]{2})</span>.*?(<ul class=/"sellerInformation/">.+?</ul>)", Pattern.DOTALL);
  // 运费
  // <span class="price_shipping">+ $6.04</span>
  static Pattern pShipping = Pattern
      .compile("<span class=/"price_shipping/">//+ //$([//d]+//.[//d]{2})</span>", Pattern.DOTALL);
  /**
   * 解析页面,获得商品列表
   *
   * @param page
   *          页面
   * @return 商品列表
   */
  private static List<AmazonGoods> parse(String page) {
    // 首先,把商品分成多个字符串片段
    // 分割符就是表格里的内容了。这个得查看HTML源代码才能找到合适的
    String[] strs = page.split("<tbody class=/"result/">");
    // 构造结果
    // 默认长度为片段的长度,呵呵
    List<AmazonGoods> list = new ArrayList<AmazonGoods>(strs.length);
    AmazonGoods goods = null;
    // 循环解析每个商品片段
    for (String str : strs) {
      // 注意,不是每个商品都有运费,所以正则最好不要写一个
      // 当然,你愿意弄复杂了也行,我个人不推荐这么做
      Matcher m = pPrice.matcher(str);
      if (m.find()) {
        goods = new AmazonGoods();
        goods.setPrice(new BigDecimal(m.group(1)));
        // 这里面包含了HTML的信息,包括Javascript内容,不过比较难删除
        // 因为有些页面文字是用js显示的,还是保留的比较好
        goods.setSeller(m.group(2));
        // 查找运费
        m = pShipping.matcher(str);
        if (m.find()) {
          goods.setShipping(new BigDecimal(m.group(1)));
        }
        // 将商品加入列表
        list.add(goods);
      } else {
        // 没有找到价格,则这部分不包含商品信息,无需继续
        continue;
      }
    }
    return list;
  }
  private static String buildTable(List<AmazonGoods> list) {
    StringBuilder b = new StringBuilder("<table>");
    b.append("<tr><th>价格</th><th>运费</th><th>商家信息</th></tr>");
    for (AmazonGoods goods : list) {
      b.append("<tr><th>" + goods.getPrice() + "</th><th>" + goods.getShipping() + "</th><th>" + goods.getSeller()
          + "</th></tr>");
    }
    b.append("</table>");
    return b.toString();
  }
  private static void saveToMySQL(List<AmazonGoods> list) {
    // 这里就用最原始的方法获得数据库连接了。
    // 数据库结构请参考AmazonGoods.sql
    // 使用test的数据库
    Connection con = null;
    PreparedStatement st = null;
    String url = "jdbc:mysql://localhost:3306/";
    String db = "test";
    String driver = "com.mysql.jdbc.Driver";
    String user = "test";
    String pass = "test";
    BigDecimal ZERO = new BigDecimal("0");
    try {
      Class.forName(driver);
      con = DriverManager.getConnection(url + db, user, pass);
      st = con.prepareStatement("insert into AmazonGoods (price,shipping,seller) values(?,?,?)");
      for (AmazonGoods goods : list) {
        st.setBigDecimal(1, goods.getPrice());
        st.setBigDecimal(2, goods.getShipping()==null?ZERO:goods.getShipping());
        st.setString(3, goods.getSeller());
        if (st.executeUpdate() <= 0) {
          throw new Exception("保存数据错误!");
        }
        st.clearParameters();
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    } finally {
      if (st != null) {
        try {
          st.close();
        } catch (Exception ex) {
        }
      }
      if (con != null) {
        try {
          con.close();
        } catch (Exception ex) {
        }
      }
    }
  }
}
 

 


四、辅助类,PageService.java

view plaincopy to clipboardprint?
package com.laozizhu.tools;  
import java.io.BufferedReader;  
import java.io.FileNotFoundException;  
import java.io.InputStream;  
import java.io.InputStreamReader;  
import java.io.OutputStream;  
import java.net.ConnectException;  
import java.net.HttpURLConnection;  
import java.net.URL;  
import java.util.zip.GZIPInputStream;  
/** 
 * 读取URL的文本工具 
 *  
 * @author 赵学庆 www.java2000.net 
 */ 
public class PageService {  
  private static final String BR = "/r/n";  
  /** 
   * 读取文本。默认使用UTF-8编码 
   *  
   * @param page 
   *          页面的URL,比如 http://www.java2000.net 
   * @return 读取到的文本字符串 
   */ 
  public static String getPage(String page) {  
    return getPage(page, "UTF-8");  
  }  
  /** 
   * 读取文本 
   *  
   * @param page 
   *          页面的URL,比如 http://www.java2000.net 
   * @param charset 
   *          页面的编码 
   * @return 读取到的文本字符串 
   */ 
  public static String getPage(String page, String charset) {  
    String str = null;  
    int count = 3;  
    do {  
      str = _getPage(page, charset);  
      if (str == null || str.length() == 0) {  
        try {  
          Thread.sleep(1000);  
        } catch (InterruptedException e) {  
          e.printStackTrace();  
        }  
      }  
    } while (str == null && count-- > 0);  
    return str;  
  }  
  private static String _getPage(String page, String charset) {  
    try {  
      URL url = new URL(page);  
      HttpURLConnection con = (HttpURLConnection) url.openConnection();  
      // 增加了浏览器的类型,就用Firefox好了,也许  
      con  
          .setRequestProperty(  
              "User-Agent",  
              "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)");  
      int index = page.indexOf("/", 10);  
      con.setRequestProperty("Host", index == -1 ? page.substring(7) : page  
          .substring(7, index));  
      InputStream is = con.getInputStream();  
      if (con.getContentEncoding() != null 
          && con.getContentEncoding().equalsIgnoreCase("gzip")) {  
        is = new GZIPInputStream(con.getInputStream());  
      }  
      BufferedReader reader = new BufferedReader(new InputStreamReader(is,  
          charset));  
      StringBuilder b = new StringBuilder();  
      String line;  
      while ((line = reader.readLine()) != null) {  
        b.append(line);  
        b.append(BR);  
      }  
      reader.close();  
      return b.toString();  
    } catch (FileNotFoundException ex) {  
      System.out.println("NOT FOUND:" + page);  
      return null;  
    } catch (ConnectException ex) {  
      System.out.println("Timeout:" + page);  
      return null;  
    } catch (Exception ex) {  
      ex.printStackTrace();  
      return null;  
    }  
  }  
  public static String postPage(String page, String msg) throws Exception {  
    URL url = new URL(page);  
    HttpURLConnection con = (HttpURLConnection) url.openConnection();  
    con.setDoOutput(true); // POST方式  
    con  
        .setRequestProperty(  
            "User-Agent",  
            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)");  
    int index = page.indexOf("/", 10);  
    con.setRequestProperty("Host", index == -1 ? page.substring(7) : page  
        .substring(7, index));  
    con.setRequestMethod("POST");  
    con.addRequestProperty("Content-Type", "application/x-www-form-urlencoded");  
    OutputStream os = con.getOutputStream(); // 输出流,写数据  
    os.write(msg.getBytes("UTF-8"));  
    InputStream is = con.getInputStream();  
    if (con.getContentEncoding() != null 
        && con.getContentEncoding().equalsIgnoreCase("gzip")) {  
      is = new GZIPInputStream(con.getInputStream());  
    }  
    BufferedReader reader = new BufferedReader(new InputStreamReader(is,  
        "UTF-8")); // 读取结果  
    StringBuilder b = new StringBuilder();  
    String line;  
    while ((line = reader.readLine()) != null) {  
      b.append(line);  
      b.append(BR);  
    }  
    os.close();  
    reader.close();  
    return b.toString();  
  }  

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/java2000_net/archive/2009/06/16/4273576.aspx

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/java2000_net/archive/2009/06/16/4273576.aspx

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
顺序如下: 1、多种字体大小显示 2、c:out标记输出 3、获取当前时间 4、include包含语句 5、建立错误处理页面的范例程序 6、jsp:forward 7、简单计数器 8、设置页面属性 9、使用GB2312编码 10、使用Big5编码 11、c:catch的用法 12、 begin、end和step的用法 13 、 循环 14、 varStatus 的四种属性 15、 的用法 16、从客户端传送数据至服务端 17、使用Unicode转义字符 18、使用朝鲜语字符集 19、JSP中最简单的国际化程序 20、错误检测 21、抛出异常 22、 的用法 23、和 的用法 24、 的用法 25、jsp-include的用法 26、汉字处理 27、网页重定向 28、自动更新网页 29、存取session 30、 的用法 31、单选型列表框 32、jsp文件中定义类 33、取得 JSP Container 版本 34、javax.servlet.jsp.JspWriter - out 对象 35、page 隐含对象 36、application 对象 37、PageContext 对象 38、Page范围 - pageContext 39、测试要显示的中文 40、IF控制符的操作 41、HttpServletRequest 接口所提供的方法 42、 网上测验 43、HttpSession - session 对象 44、 多选型列表框 45、解决浏览器 cache 的问题 46、使用 EL、JSTL 处理表单数据 47、 EL隐含对象 param、paramValues 48、EL隐含对象 pageContext 49、EL算术运算符 50、EL关系运算符 51、EL的运算符 52、选择钮的使用 53、检查框的使用 54、群组检查框的使用 55、数字、货币、百分数格式化 56、日期格式化 57、JSTL设置语言地区 58、Cookie数据的存取 59、session有效时间的设置与取得 60、session时间与ID 61、Cookie有效时间的设置 62、利用隐藏字段传送数据 63、JSP 使用 JavaBean 的方法 64、JSP 使用 JavaBean 65、范围为 Page 的 JavaBean范例程序 66、范围为 Request的 JavaBean 67、范围为 Session 的 JavaBean 68、范围为 Application 的 JavaBean 69、删除 JavaBean 70、url重组 71、Switch语句 72、环境变量 73、forward重定向 74、文件的建立与删除 75、取得文件属性 76、取得目录中的文件 77、目录的建立与删除 78、自Cookie存取日期/时间数据 79、管理Session变量 80、数据库中的记录数与记录指针位置 81、利用absolute方法设置记录位置 82、使用jsp指令生成Word文档 83、JSP网页模板 84、判断是否空白文件 85、cookie 用户登录次数 86、获取用户的真实IP地址 87、获取用户的浏览器信息 88、在客户端进行数据检查 89、在JSP中获取当前绝对路径 90、读取表单中所有参数 91、分行写入数据 92、显示请求URL 93、判断session是否过期 94、参数式查询数据库 95、取得数据库中各栏名称 96、使用JavaBean、设置和获取Bean的属性 97、设置Bean的一个属性与输入参数关联 98、实现基于数据库的站内搜索 99、DOM读取XML文档 100、SAX读取XML文档
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值