用java将网页保存为mht格式

http://blog.csdn.net/lishigui/article/details/5749952

这是我从网上搜到的,用java将网页保存为mht格式,感觉不错,所以就共享一下给大家,让朋友们也学习学习!

需要用到的jar包有java mail,下载地址:http://java.sun.com/products/javamail/downloads/index.html

还有htmlparser,下载地址:http://sourceforge.net/projects/htmlparser/files/

[java]  view plain copy
  1. package com.tag;     
  2. import java.io.BufferedInputStream;  
  3. import java.io.UnsupportedEncodingException;  
  4. import java.io.ByteArrayInputStream;  
  5. import java.io.File;  
  6. import java.io.FileOutputStream;  
  7. import java.io.IOException;  
  8. import java.io.InputStream;  
  9. import java.io.OutputStream;  
  10. import java.net.MalformedURLException;  
  11. import java.net.URLConnection;  
  12. import java.net.URL;  
  13. import java.util.ArrayList;  
  14. import java.util.HashMap;  
  15. import java.util.Iterator;  
  16. import java.util.Map;  
  17. import java.util.Properties;  
  18. import java.util.StringTokenizer;  
  19.   
  20. import org.htmlparser.Parser;  
  21. import org.htmlparser.Tag;  
  22. import org.htmlparser.filters.TagNameFilter;  
  23. import org.htmlparser.lexer.Lexer;  
  24. import org.htmlparser.lexer.Page;  
  25. import org.htmlparser.util.DefaultParserFeedback;  
  26. import org.htmlparser.util.NodeList;  
  27. import org.htmlparser.util.ParserException;  
  28. import javax.activation.DataHandler;  
  29. import javax.activation.DataSource;  
  30. import javax.activation.MimetypesFileTypeMap;  
  31. import javax.mail.Authenticator;  
  32. import javax.mail.Message;  
  33. import javax.mail.PasswordAuthentication;  
  34. import javax.mail.Session;  
  35. import javax.mail.internet.InternetAddress;  
  36. import javax.mail.internet.MimeBodyPart;  
  37. import javax.mail.internet.MimeMessage;  
  38. import javax.mail.internet.MimeMultipart;  
  39.   
  40. /** 
  41.  *  
  42.  * mht文件解析类 
  43.  *  
  44.  */  
  45. public class HtmlToMht {  
  46.       
  47.     /** 网页编码 */  
  48.     private String strEncoding = null;  
  49.       
  50.     // mht格式附加信息  
  51.     private String from = "[email protected]";  
  52.     private String to = "[email protected]";  
  53.     private String subject = "blog.csdn.net/lishigui";  
  54.     private String cc;  
  55.     private String bcc;  
  56.       
  57.     public static void main(String[] args) {  
  58.         new HtmlToMht("http://blog.csdn.net/lishigui","C:");  
  59.     }  
  60.   
  61.     /** 
  62.      * 构造方法:初始化<br> 
  63.      * 输入参数:strUrl 网页地址;  strFilePath 保存路径<br> 
  64.      */  
  65.     public HtmlToMht(String strUrl, String strFilePath) {  
  66.   
  67.         try {  
  68.             byte[] bText = null;  
  69.             //取得页面内容  
  70.             bText = downBinaryFile(strUrl);  
  71.             String strText = new String(bText);  
  72.             strEncoding = strText.split("charset="2)[1];  
  73.             strEncoding = strEncoding.split("/"")[0];  
  74.             System.err.println(strEncoding);  
  75.             try {  
  76.                 strText = new String(bText, 0, bText.length, strEncoding);  
  77.             } catch (UnsupportedEncodingException e) {  
  78.                 e.printStackTrace();  
  79.             }  
  80.             if (strText == null){  
  81.                 return;  
  82.             }  
  83.             compile(new URL(strUrl),strText,strFilePath);  
  84.   
  85.         } catch (MalformedURLException e) {  
  86.             e.printStackTrace();  
  87.             return;  
  88.         }  
  89.     }  
  90.   
  91.     /** 
  92.      * 方法说明:执行下载操作<br> 
  93.      * 输入参数:strWeb 网页地址; strText 网页内容; strFilePath 保存路径<br> 
  94.      * 返回类型:boolean<br> 
  95.      */  
  96.     public boolean compile(URL strWeb, String strText, String strFilePath) {  
  97.         if (strWeb == null || strText == null || strFilePath == null){  
  98.             return false;  
  99.         }  
  100.         HashMap urlMap = new HashMap();  
  101.         NodeList nodes = new NodeList();  
  102.         try {  
  103.             Parser parser = createParser(strText);  
  104.             nodes = parser.parse(null);  
  105.         } catch (ParserException e) {  
  106.             e.printStackTrace();  
  107.         }  
  108.   
  109.         URL strWebB = extractAllScriptNodes(nodes);  
  110.         if(strWebB == null || strWebB.equals("")){  
  111.             strWebB = strWeb;  
  112.         }  
  113.         ArrayList urlScriptList = extractAllScriptNodes(nodes, urlMap, strWebB);  
  114.         ArrayList urlImageList = extractAllImageNodes(nodes, urlMap, strWebB);  
  115.         if(strWebB == null || strWebB.equals("")){  
  116.             for (Iterator iter = urlMap.entrySet().iterator(); iter.hasNext();) {  
  117.                 Map.Entry entry = (Map.Entry) iter.next();  
  118.                 String key = (String) entry.getKey();  
  119.                 String val = (String) entry.getValue();  
  120.                 strText = strText.replace(val, key);  
  121.             }  
  122.         }  
  123.           
  124.         try {  
  125.             createMhtArchive(strText, urlScriptList, urlImageList, strWeb, strFilePath);  
  126.         } catch (Exception e) {  
  127.             e.printStackTrace();  
  128.             return false;  
  129.         }  
  130.   
  131.         return true;  
  132.   
  133.     }  
  134.       
  135.     /** 
  136.      * 方法说明:下载文件操作<br> 
  137.      * 输入参数:url 文件路径<br> 
  138.      * 返回类型:byte[]<br> 
  139.      */  
  140.     public  byte[] downBinaryFile(String url){  
  141.         System.out.println(url);  
  142.         try {  
  143.             URL cUrl = new URL(url);  
  144.             URLConnection uc = cUrl.openConnection();
        uc.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");  
  145.             // String contentType = this.strType;  
  146.             int contentLength = uc.getContentLength();  
  147.             if (contentLength > 0) {  
  148.                 InputStream raw = uc.getInputStream();  
  149.                 InputStream in = new BufferedInputStream(raw);  
  150.                 byte[] data = new byte[contentLength];  
  151.                 int bytesRead = 0;  
  152.                 int offset = 0;  
  153.                 while (offset < contentLength) {  
  154.                     bytesRead = in.read(data, offset, data.length - offset);  
  155.                     if (bytesRead == -1) {  
  156.                         break;  
  157.                     }  
  158.                     offset += bytesRead;  
  159.                 }  
  160.                 in.close();  
  161.                 raw.close();  
  162.                 return data;  
  163.             }  
  164.         } catch (MalformedURLException e) {  
  165.             e.printStackTrace();  
  166.         } catch (IOException e) {  
  167.             e.printStackTrace();  
  168.         }  
  169.       
  170.         return null;  
  171.   
  172.     }  
  173.   
  174.     /** 
  175.      * 方法说明:建立HTML parser<br> 
  176.      * 输入参数:inputHTML 网页文本内容<br> 
  177.      * 返回类型:HTML parser<br> 
  178.      */  
  179.     private Parser createParser(String inputHTML) {  
  180.         Lexer mLexer = new Lexer(new Page(inputHTML));  
  181.         return new Parser(mLexer, new DefaultParserFeedback(  
  182.                 DefaultParserFeedback.QUIET));  
  183.     }  
  184.   
  185.     /** 
  186.      * 方法说明:抽取基础URL地址<br> 
  187.      * 输入参数:nodes 网页标签集合<br> 
  188.      * 返回类型:URL<br> 
  189.      */  
  190.     private URL extractAllScriptNodes(NodeList nodes) {  
  191.   
  192.         NodeList filtered = nodes.extractAllNodesThatMatch(new TagNameFilter(  
  193.         "BASE"), true);  
  194.   
  195.         if (filtered != null && filtered.size() > 0) {  
  196.             Tag tag = (Tag) filtered.elementAt(0);  
  197.             String href = tag.getAttribute("href");  
  198.             if (href != null && href.length() > 0) {  
  199.                 try {  
  200.                     return new URL(href);  
  201.                 } catch (MalformedURLException e) {  
  202.                     e.printStackTrace();  
  203.   
  204.                 }  
  205.             }  
  206.         }  
  207.         return null;  
  208.     }  
  209.   
  210.     /** 
  211.      * 方法说明:抽取网页包含的css,js链接<br> 
  212.      * 输入参数:nodes 网页标签集合; urlMap 已存在的url集合<br> 
  213.      * 返回类型:css,js链接的集合<br> 
  214.      */  
  215.     private ArrayList extractAllScriptNodes(NodeList nodes, HashMap urlMap,  
  216.             URL strWeb) {  
  217.   
  218.         ArrayList urlList = new ArrayList();  
  219.         NodeList filtered = nodes.extractAllNodesThatMatch(new TagNameFilter(  
  220.                 "script"), true);  
  221.         //遍历页面所有的script结点  
  222.         for (int i = 0; i < filtered.size(); i++) {  
  223.             Tag tag = (Tag) filtered.elementAt(i);  
  224.             String src = tag.getAttribute("src");  
  225.             System.out.println("script src="+src);  
  226.             // Handle external css file's url  
  227.             if (src != null && src.length() > 0) {  
  228.                 String innerURL = src;  
  229.                 //取得绝对路径,即把?号后面的除掉  
  230.                 String absoluteURL = makeAbsoluteURL(strWeb, innerURL);  
  231.                 if (absoluteURL != null && !urlMap.containsKey(absoluteURL)) {  
  232.                     urlMap.put(absoluteURL, innerURL);  
  233.                     ArrayList urlInfo = new ArrayList();  
  234.                     urlInfo.add(innerURL);  
  235.                     urlInfo.add(absoluteURL);  
  236.                     urlList.add(urlInfo);  
  237.                 }  
  238.                 tag.setAttribute("src", absoluteURL);  
  239.             }  
  240.         }  
  241.   
  242.         filtered = nodes.extractAllNodesThatMatch(new TagNameFilter("link"),true);  
  243.         for (int i = 0; i < filtered.size(); i++) {  
  244.             Tag tag = (Tag) filtered.elementAt(i);  
  245.             String type = tag.getAttribute("type");  
  246.             String rel = tag.getAttribute("rel");  
  247.             String href = tag.getAttribute("href");  
  248.             boolean isCssFile = false;  
  249.             if (rel != null) {  
  250.                 isCssFile = rel.indexOf("stylesheet") != -1;  
  251.             } else if (type != null) {  
  252.                 isCssFile |= type.indexOf("text/css") != -1;  
  253.             }  
  254.   
  255.             if (isCssFile && href != null && href.length() > 0) {  
  256.                 String innerURL = href;  
  257.                 System.out.println("css link="+href);  
  258.                 String absoluteURL = makeAbsoluteURL(strWeb, innerURL);  
  259.                 if (absoluteURL != null && !urlMap.containsKey(absoluteURL)) {  
  260.                     urlMap.put(absoluteURL, innerURL);  
  261.                     ArrayList urlInfo = new ArrayList();  
  262.                     urlInfo.add(innerURL);  
  263.                     urlInfo.add(absoluteURL);  
  264.                     urlList.add(urlInfo);  
  265.                 }  
  266.                 tag.setAttribute("href", absoluteURL);  
  267.             }  
  268.         }  
  269.   
  270.         return urlList;  
  271.   
  272.     }  
  273.   
  274.     /** 
  275.      * 方法说明:抽取网页包含的图像链接<br> 
  276.      * 输入参数:nodes 网页标签集合; urlMap 已存在的url集合; strWeb 网页地址<br> 
  277.      * 返回类型:图像链接集合<br> 
  278.      */  
  279.     private ArrayList extractAllImageNodes(NodeList nodes, HashMap urlMap,  
  280.             URL strWeb) {  
  281.   
  282.         ArrayList urlList = new ArrayList();  
  283.         NodeList filtered = nodes.extractAllNodesThatMatch(new TagNameFilter(  
  284.                 "IMG"), true);  
  285.   
  286.         for (int i = 0; i < filtered.size(); i++) {  
  287.             Tag tag = (Tag) filtered.elementAt(i);  
  288.             String src = tag.getAttribute("src");  
  289.             System.out.println("IMG src="+src);  
  290.             // Handle external css file's url  
  291.             if (src != null && src.length() > 0) {  
  292.                 String innerURL = src;  
  293.                 String absoluteURL = makeAbsoluteURL(strWeb, innerURL);  
  294.                 if (absoluteURL != null && !urlMap.containsKey(absoluteURL)) {  
  295.                     urlMap.put(absoluteURL, innerURL);  
  296.                     ArrayList urlInfo = new ArrayList();  
  297.                     urlInfo.add(innerURL);  
  298.                     urlInfo.add(absoluteURL);  
  299.                     urlList.add(urlInfo);  
  300.                 }  
  301.                 tag.setAttribute("src", absoluteURL);  
  302.             }  
  303.         }  
  304.         return urlList;  
  305.     }  
  306.   
  307.     /** 
  308.      * 方法说明:相对路径转绝对路径<br> 
  309.      * 输入参数:strWeb 网页地址; innerURL 相对路径链接<br> 
  310.      * 返回类型:绝对路径链接<br> 
  311.      */  
  312.     public  String makeAbsoluteURL(URL strWeb, String innerURL) {  
  313.   
  314.         // TODO Auto-generated method stub  
  315.         // 去除后缀(即参数去掉)  
  316.         int pos = innerURL.indexOf("?");  
  317.         if (pos != -1) {  
  318.             innerURL = innerURL.substring(0, pos);  
  319.         }  
  320.         if(strWeb == null || strWeb.equals("")){  
  321.             if(innerURL.startsWith("//")){  
  322.                 innerURL = "http:"+innerURL;  
  323.             }  
  324.         }  
  325.         if (innerURL != null  
  326.         && innerURL.toLowerCase().indexOf("http") == 0) {  
  327.             return innerURL;  
  328.         }  
  329.         URL linkUri = null;  
  330.         try {  
  331.             linkUri = new URL(strWeb, innerURL);  
  332.         } catch (MalformedURLException e) {  
  333.             e.printStackTrace();  
  334.             return null;  
  335.   
  336.         }  
  337.   
  338.         String absURL = linkUri.toString();  
  339.         absURL = absURL.replace("../""");  
  340.         absURL = absURL.replace("./""");  
  341.         System.out.println(absURL);  
  342.   
  343.         return absURL;  
  344.   
  345.     }  
  346.   
  347.     /** 
  348.      * 方法说明:创建mht文件<br> 
  349.      * 输入参数:content 网页文本内容; urlScriptList 脚本链接集合; urlImageList 图片链接集合 
  350.      * strWeb 网页地址; strFilePath 保存路径<br> 
  351.      * 返回类型:<br> 
  352.      */  
  353.     private void createMhtArchive(String content, ArrayList urlScriptList,  
  354.             ArrayList urlImageList, URL strWeb, String strFilePath) throws Exception {  
  355.   
  356.         // Instantiate a Multipart object  
  357.         MimeMultipart mp = new MimeMultipart("related");  
  358.   
  359.         Properties properties = new Properties();  
  360.         // 设置系统属性  
  361.         properties = System.getProperties();  
  362.         properties.put("mail.smtp.host""smtp.126.com");  
  363.         properties.put("mail.smtp.auth""true");  
  364.         // 邮件会话对象  
  365.         Session session = Session.getDefaultInstance(properties,  
  366.                 new Email_auth(from, ""));  
  367.   
  368.         // props.put("mail.smtp.host", smtp);  
  369.         MimeMessage msg = new MimeMessage(session);  
  370.   
  371.         // set mailer  
  372.         msg.setHeader("X-Mailer""Code Manager .SWT");  
  373.   
  374.         // set from  
  375.         if (from != null) {  
  376.             msg.setFrom(new InternetAddress(from));  
  377.         }  
  378.   
  379.         // set subject  
  380.         if (subject != null) {  
  381.             msg.setSubject(subject);  
  382.         }  
  383.   
  384.         // to  
  385.         if (to != null) {  
  386.             InternetAddress[] toAddresses = getInetAddresses(to);  
  387.             msg.setRecipients(Message.RecipientType.TO, toAddresses);  
  388.   
  389.         }  
  390.   
  391.         // cc  
  392.         if (cc != null) {  
  393.             InternetAddress[] ccAddresses = getInetAddresses(cc);  
  394.             msg.setRecipients(Message.RecipientType.CC, ccAddresses);  
  395.         }  
  396.   
  397.         // bcc  
  398.         if (bcc != null) {  
  399.             InternetAddress[] bccAddresses = getInetAddresses(bcc);  
  400.             msg.setRecipients(Message.RecipientType.BCC, bccAddresses);  
  401.         }  
  402.   
  403.         // 设置网页正文  
  404.         MimeBodyPart bp = new MimeBodyPart();  
  405.         bp.setText(content, strEncoding);  
  406.         bp.addHeader("Content-Type""text/html;charset=" + strEncoding);  
  407.         bp.addHeader("Content-Location", strWeb.toString());  
  408.         mp.addBodyPart(bp);  
  409.   
  410.         int urlCount = urlScriptList.size();  
  411.   
  412.         for (int i = 0; i < urlCount; i++) {  
  413.   
  414.             bp = new MimeBodyPart();  
  415.             ArrayList urlInfo = (ArrayList) urlScriptList.get(i);  
  416.             String absoluteURL = urlInfo.get(1).toString();  
  417.   
  418.             bp.addHeader("Content-Location",javax.mail.internet.MimeUtility  
  419.             .encodeWord(java.net.URLDecoder.decode(absoluteURL, strEncoding)));  
  420.   
  421.             DataSource source = new AttachmentDataSource(absoluteURL, "text");  
  422.             bp.setDataHandler(new DataHandler(source));  
  423.   
  424.             mp.addBodyPart(bp);  
  425.   
  426.         }  
  427.   
  428.         urlCount = urlImageList.size();  
  429.   
  430.         for (int i = 0; i < urlCount; i++) {  
  431.   
  432.             bp = new MimeBodyPart();  
  433.             ArrayList urlInfo = (ArrayList) urlImageList.get(i);  
  434.   
  435.             // String url = urlInfo.get(0).toString();  
  436.             String absoluteURL = urlInfo.get(1).toString();  
  437.             bp.addHeader("Content-Location",javax.mail.internet.MimeUtility  
  438.             .encodeWord(java.net.URLDecoder.decode(absoluteURL, strEncoding)));  
  439.   
  440.             DataSource source = new AttachmentDataSource(absoluteURL, "image");  
  441.             bp.setDataHandler(new DataHandler(source));  
  442.   
  443.             mp.addBodyPart(bp);  
  444.         }  
  445.         msg.setContent(mp);  
  446.         // write the mime multi part message to a file  
  447.         msg.writeTo(new FileOutputStream(strFilePath+"//"+strWeb.toString().split("/")[strWeb.toString().split("/").length-1]+".mht"));  
  448.         // Transport.send(msg);  
  449.   
  450.     }  
  451.   
  452.     private InternetAddress[] getInetAddresses(String emails) throws Exception {  
  453.         ArrayList list = new ArrayList();  
  454.         StringTokenizer tok = new StringTokenizer(emails, ",");  
  455.         while (tok.hasMoreTokens()) {  
  456.             list.add(tok.nextToken());  
  457.         }  
  458.         int count = list.size();  
  459.         InternetAddress[] addresses = new InternetAddress[count];  
  460.         for (int i = 0; i < count; i++) {  
  461.             addresses[i] = new InternetAddress(list.get(i).toString());  
  462.         }  
  463.         return addresses;  
  464.   
  465.     }  
  466.   
  467.     class AttachmentDataSource implements DataSource {  
  468.   
  469.         private MimetypesFileTypeMap map = new MimetypesFileTypeMap();  
  470.         private String strUrl;  
  471.         private String strType;  
  472.         private byte[] dataSize = null;  
  473.   
  474.         /** 
  475.          *  
  476.          * This is some content type maps. 
  477.          */  
  478.         private Map normalMap = new HashMap();  
  479.         {  
  480.             // Initiate normal mime type map  
  481.             // Images  
  482.             normalMap.put("image""image/jpeg");  
  483.             normalMap.put("text""text/plain");  
  484.   
  485.         }  
  486.   
  487.         public AttachmentDataSource(String strUrl, String strType) {  
  488.             this.strType = strType;  
  489.             this.strUrl = strUrl;  
  490.             strUrl = strUrl.trim();  
  491.             strUrl = strUrl.replaceAll(" ""%20");  
  492.             dataSize = downBinaryFile(strUrl);  
  493.   
  494.         }  
  495.   
  496.         public String getContentType() {  
  497.             return getMimeType(getName());  
  498.         }  
  499.   
  500.         public String getName() {  
  501.             char separator = File.separatorChar;  
  502.             if (strUrl.lastIndexOf(separator) >= 0)  
  503.                 return strUrl.substring(strUrl.lastIndexOf(separator) + 1);  
  504.             return strUrl;  
  505.   
  506.         }  
  507.   
  508.         private String getMimeType(String fileName) {  
  509.             String type = (String) normalMap.get(strType);  
  510.             if (type == null) {  
  511.                 try {  
  512.                     type = map.getContentType(fileName);  
  513.                 } catch (Exception e) {  
  514.                 }  
  515.                 if (type == null) {  
  516.                     type = "application/octet-stream";  
  517.                 }  
  518.             }  
  519.             return type;  
  520.   
  521.         }  
  522.   
  523.         public InputStream getInputStream() throws IOException {  
  524.             if (dataSize == null)  
  525.                 dataSize = new byte[0];  
  526.             return new ByteArrayInputStream(dataSize);  
  527.         }  
  528.   
  529.         public OutputStream getOutputStream() throws IOException {  
  530.             return new java.io.ByteArrayOutputStream();  
  531.         }  
  532.   
  533.     }  
  534.   
  535.     class Email_auth extends Authenticator {  
  536.   
  537.         String auth_user;  
  538.         String auth_password;  
  539.   
  540.         public Email_auth() {  
  541.             super();  
  542.         }  
  543.   
  544.         public Email_auth(String user, String password) {  
  545.             super();  
  546.             setUsername(user);  
  547.             setUserpass(password);  
  548.   
  549.         }  
  550.   
  551.         public void setUsername(String username) {  
  552.             auth_user = username;  
  553.         }  
  554.   
  555.         public void setUserpass(String userpass) {  
  556.             auth_password = userpass;  
  557.         }  
  558.   
  559.         public PasswordAuthentication getPasswordAuthentication() {  
  560.             return new PasswordAuthentication(auth_user, auth_password);  
  561.         }  
  562.   
  563.     }  
  564.   
  565. }  


你可能感兴趣的:(java)