zoukankan      html  css  js  c++  java
  • 博客园文章爬取代码

     转载 http://blog.csdn.net/rongyongfeikai2/article/details/7798838

    最近,在看博客园上的文章。希望能够爬取指定的博客园的文章,并保存为WORD文档的形式。所以,趁着周末休息,花了半天时间把它给做了出来。

    完整代码下载地址:http://download.csdn.net/detail/rongyongfeikai2/4462085

    首先,我们爬取的文章,应该包括三个部分:标题、链接和正文。所以,我们用一个POJO来存储文章。

    1. package com.BlogCrawler.Model;  
    2. /* 
    3.  * author:Tammy Pi 
    4.  * function:写入doc文档的类 
    5.  * Email:victory_pj@163.com 
    6.  */  
    7. public class Document {  
    8.   
    9.     //属性域,分别代表文章的标题、内容和文章的链接  
    10.     private String title;  
    11.     private String content;  
    12.     private String link;  
    13.       
    14.     public String getTitle() {  
    15.         return title;  
    16.     }  
    17.     public void setTitle(String title) {  
    18.         this.title = title;  
    19.     }  
    20.     public String getContent() {  
    21.         return content;  
    22.     }  
    23.     public void setContent(String content) {  
    24.         this.content = content;  
    25.     }  
    26.     public String getLink() {  
    27.         return link;  
    28.     }  
    29.     public void setLink(String link) {  
    30.         this.link = link;  
    31.     }  
    32. }  

    定义好Document后,我们需要爬取指定URL对应的文章列表,再根据文章列表中文章所对应的链接,提取其对应的文章,并分析文章内容。

    目前分析博客园列表结构,它的文章列表是放在class="post"或者class="postTitle"的div中。我们用HttpClient包爬取相应的文章后,再用HtmlParser分析DOM,提取出文章列表。对于博客园正文结构,分析得,它的正文是放在id="cnblogs_post_body",同样也可以用HttpClient包将其提取出来。

    提取页面和分析页面的代码为:

    1. package com.BlogCrawler.Fetcher;  
    2. import java.io.BufferedInputStream;  
    3. import java.io.InputStream;  
    4. import java.util.*;  
    5. import java.util.regex.Pattern;  
    6. import org.apache.commons.httpclient.HttpClient;  
    7. import org.apache.commons.httpclient.HttpStatus;  
    8. import org.apache.commons.httpclient.methods.GetMethod;  
    9. import org.htmlparser.Node;  
    10. import org.htmlparser.Parser;  
    11. import org.htmlparser.filters.HasAttributeFilter;  
    12. import org.htmlparser.filters.TagNameFilter;  
    13. import org.htmlparser.util.NodeList;  
    14. import org.htmlparser.util.ParserException;  
    15. /* 
    16.  * author:Tammy Pi 
    17.  * function:用于爬取文章的类,针对于博客园 
    18.  * Email:victory_pj@163.com 
    19.  */  
    20. public class FetcherHelper {  
    21.   
    22.     //根据url爬取url指向的页面的内容,并返回  
    23.     public String getPageContent(String url){  
    24.           
    25.         StringBuffer sb = new StringBuffer();  
    26.         HttpClient httpClient = new HttpClient();  
    27.         GetMethod getMethod = new GetMethod(url);  
    28.         BufferedInputStream reader = null;  
    29.           
    30.         try{  
    31.               
    32.             int statusCode = httpClient.executeMethod(getMethod);  
    33.               
    34.             //判断状态  
    35.             if(statusCode==HttpStatus.SC_OK){  
    36.                   
    37.                 InputStream inputStream = getMethod.getResponseBodyAsStream();  
    38.                 reader = new BufferedInputStream(inputStream);  
    39.                   
    40.                 int index;  
    41.                 byte[] buffer = new byte[1024];  
    42.                   
    43.                 while((index=reader.read(buffer))!=-1){  
    44.                       
    45.                     sb.append(new String(buffer,0,index,"utf-8"));  
    46.                 }  
    47.             }else{  
    48.                   
    49.                 System.out.println("爬取出错。错误代码:"+statusCode);  
    50.             }  
    51.         }catch(Exception ex){  
    52.               
    53.             ex.printStackTrace();  
    54.         }  
    55.           
    56.         return sb.toString();  
    57.     }  
    58.       
    59.     //利用HTMLParser过滤文章内容  
    60.     public String filterContent(String page,String tag,String attr,String value){  
    61.           
    62.         TagNameFilter tagFilter = new TagNameFilter(tag);  
    63.         Parser parser = new Parser();  
    64.         parser = parser.createParser(page,"utf-8");  
    65.         NodeList tagList = null;  
    66.         String rtn = "";  
    67.           
    68.         try {  
    69.             tagList = parser.parse(tagFilter);  
    70.             for(int u=0;u<tagList.size();u++) {  
    71.                   
    72.                 String html = tagList.elementAt(u).toHtml();  
    73.                   
    74.                 HasAttributeFilter attrFilter = new HasAttributeFilter(attr,value);  
    75.                 Parser parser2 = parser.createParser(html,"utf-8");  
    76.                 NodeList list2 = parser2.parse(attrFilter);  
    77.                   
    78.                 if(list2.size()>0){  
    79.   
    80.                     rtn = list2.elementAt(0).toHtml();  
    81.                       
    82.                 }  
    83.             }  
    84.         } catch (ParserException e) {  
    85.             // TODO Auto-generated catch block  
    86.             e.printStackTrace();  
    87.         }  
    88.           
    89.         return rtn;  
    90.     }  
    91.       
    92.     //利用HTMLParser分析文章列表  
    93.     public List<com.BlogCrawler.Model.Document> htmlFilter(String page,String tag,String attr,String value){  
    94.           
    95.         String rtn = "";  
    96.         TagNameFilter tagFilter = new TagNameFilter(tag);  
    97.         Parser parser = new Parser();  
    98.         parser = parser.createParser(page,"utf-8");  
    99.         NodeList tagList = null;  
    100.         List<com.BlogCrawler.Model.Document> list = new ArrayList<com.BlogCrawler.Model.Document>();  
    101.           
    102.         try {  
    103.             tagList = parser.parse(tagFilter);  
    104.               
    105.             //遍历过滤后的tagList  
    106.             HasAttributeFilter attrFilter = new HasAttributeFilter(attr,value);  
    107.             NodeList list2 = tagList.extractAllNodesThatMatch(attrFilter);  
    108.             //过滤得到h2,针对博客园的过滤  
    109.             String html = list2.toHtml();  
    110.               
    111.             Parser parser2 = parser.createParser(html,"utf-8");  
    112.             NodeList list3 = null;  
    113.             if(value.equals("post")){  
    114.                   
    115.                 list3 = parser2.parse(new TagNameFilter("h2"));  
    116.             }else if(value.endsWith("postTitle")){  
    117.                   
    118.                 list3 = parser2.parse(new TagNameFilter("a"));  
    119.             }  
    120.               
    121.             for(int i=0;i<list3.size();i++) {  
    122.                   
    123.                 Node node = list3.elementAt(i);  
    124.                   
    125.                 com.BlogCrawler.Model.Document doc = new com.BlogCrawler.Model.Document();  
    126.                 doc.setTitle(node.toPlainTextString());  
    127.                   
    128.                 String html1 = node.toHtml();  
    129.                 html1 = html1.substring(html1.indexOf("href=\"")+6);  
    130.                 html1 = html1.substring(0,html1.indexOf("\""));  
    131.                   
    132.                 doc.setLink(html1);  
    133.                   
    134.                 //获得内容  
    135.                 doc.setContent(filterContent(getPageContent(doc.getLink()),"div","id","cnblogs_post_body"));  
    136.                 list.add(doc);  
    137.             }  
    138.               
    139.         } catch (ParserException e) {  
    140.             // TODO Auto-generated catch block  
    141.             e.printStackTrace();  
    142.         }  
    143.           
    144.         return list;  
    145.     }  
    146.       
    147.     //用于测试的主函数  
    148.     public static void main(String[] args){  
    149.           
    150.         FetcherHelper helper = new FetcherHelper();  
    151.         String rtn = helper.getPageContent("http://www.cnblogs.com/passzh/default.html?OnlyTitle=1");  
    152.           
    153.         if(rtn.indexOf("postTitle")==-1){  
    154.               
    155.             helper.htmlFilter(rtn,"div","class", "post");  
    156.         }else{  
    157.               
    158.             System.out.println("进入");  
    159.             helper.htmlFilter(rtn,"div","class", "postTitle");  
    160.         }  
    161.     }  
    162. }  

    最后,我们将文章写入doc文档中,这是就是用IText.jar包,它提供了HtmlWorker类,可以很方便的将HTML按照格式写入Word文档中。写入Word文档的代码为:

    1. package com.BlogCrawler.DocHelper;  
    2. import java.awt.Color;  
    3. import java.io.*;  
    4. import com.lowagie.text.Document;  
    5. import com.lowagie.text.DocumentException;  
    6. import com.lowagie.text.Element;  
    7. import com.lowagie.text.Font;  
    8. import com.lowagie.text.PageSize;  
    9. import com.lowagie.text.Paragraph;  
    10. import com.lowagie.text.Rectangle;  
    11. import com.lowagie.text.html.simpleparser.HTMLWorker;  
    12. import com.lowagie.text.html.simpleparser.StyleSheet;  
    13. import com.lowagie.text.rtf.RtfWriter2;  
    14. import java.util.*;  
    15. /* 
    16.  * author:Tammy Pi 
    17.  * function:写入doc文档的类 
    18.  * Email:victory_pj@163.com 
    19.  */  
    20. public class DocHelper {  
    21.   
    22.     private BufferedWriter writer = null;  
    23.     private String path = "c:\\Blog\\";  
    24.     //定义A4纸张  
    25.     private Rectangle pageSize = new Rectangle(PageSize.A4);  
    26.     private Document doc = null;  
    27.       
    28.     public void docHelper(String fileName,List<com.BlogCrawler.Model.Document> list) {  
    29.           
    30.         try {  
    31.             //判断路径是否存在  
    32.             if(!new File(path).exists()){  
    33.                   
    34.                 new File(path).mkdir();  
    35.             }  
    36.             //判断文件是否存在  
    37.             if(!new File(path+fileName).exists()){  
    38.                   
    39.                 new File(path+fileName).createNewFile();  
    40.             }  
    41.               
    42.             File file = new File(path+fileName);  
    43.             if(!(file.canRead()&&file.canWrite())){  
    44.                   
    45.                 System.out.println("您不具有此word文档的读写操作权限!");  
    46.                 return;  
    47.             }  
    48.               
    49.             pageSize = pageSize.rotate();  
    50.             //创建word文档,并设置纸张大小  
    51.             doc = new Document(pageSize,80,80,50,50);  
    52.               
    53.             //创建一个word文档的书写器  
    54.             RtfWriter2.getInstance(doc,new FileOutputStream(path + fileName));  
    55.             doc.open();  
    56.               
    57.             //设置标题的格式  
    58.             Paragraph titleParagraph = null;  
    59.             Paragraph contentGraph = null;  
    60.               
    61.             //循环遍历Document  
    62.             for(int i=0;i<list.size();i++) {  
    63.                   
    64.                 com.BlogCrawler.Model.Document document = list.get(i);  
    65.                   
    66.                 //书写blog文章的头部  
    67.                 System.out.println(document.getTitle());  
    68.                 titleParagraph = new Paragraph(document.getTitle(),new Font(Font.NORMAL,18,Font.BOLD,new Color(0,0,0)));  
    69.                 //标题居中  
    70.                 titleParagraph.setAlignment(Element.ALIGN_CENTER);  
    71.                 try {  
    72.                     doc.add(titleParagraph);  
    73.                       
    74.                     //书写内容  
    75.                     StyleSheet ss = new StyleSheet();  
    76.                     List htmlList = HTMLWorker.parseToList(new StringReader(document.getContent()), ss);  
    77.                       
    78.                     for(int j=0;j<htmlList.size();j++) {  
    79.                           
    80.                         Element e = (Element) htmlList.get(j);  
    81.                         Paragraph par = new Paragraph();  
    82.                         par.add(e);  
    83.                           
    84.                         doc.add(par);  
    85.                     }  
    86.                 } catch (DocumentException e) {  
    87.                     // TODO Auto-generated catch block  
    88.                     e.printStackTrace();  
    89.                 }  
    90.             }  
    91.               
    92.         } catch (IOException e) {  
    93.             // TODO Auto-generated catch block  
    94.             e.printStackTrace();  
    95.         } finally{  
    96.               
    97.             if(writer!=null){  
    98.                   
    99.                 //关闭文件输出流  
    100.                 try {  
    101.                     writer.close();  
    102.                 } catch (IOException e) {  
    103.                     // TODO Auto-generated catch block  
    104.                     e.printStackTrace();  
    105.                 }  
    106.             }  
    107.               
    108.             if(doc!=null){  
    109.                   
    110.                 doc.close();  
    111.             }  
    112.         }  
    113.     }  
    114.       
    115.     public static void main(String[] args){  
    116.           
    117.         DocHelper docHelper = new DocHelper();  
    118.           
    119.         com.BlogCrawler.Model.Document doc1 = new com.BlogCrawler.Model.Document();  
    120.         doc1.setTitle("标题1");  
    121.         doc1.setContent("内容1");  
    122.           
    123.         com.BlogCrawler.Model.Document doc2 = new com.BlogCrawler.Model.Document();  
    124.         doc2.setTitle("标题2");  
    125.         doc2.setContent("内容2");  
    126.           
    127.         List<com.BlogCrawler.Model.Document> list = new ArrayList<com.BlogCrawler.Model.Document>();  
    128.         list.add(doc1);  
    129.         list.add(doc2);  
    130.         docHelper.docHelper("卧龙居.doc",list);  
    131.           
    132.         System.out.println("word文档书写完成!");  
    133.     }  
    134. }  

    最后,程序要运行,自然要有一个入口类。代码为:

    1. package com.BlogCrawler.DocHelper;  
    2. import com.BlogCrawler.Fetcher.FetcherHelper;  
    3. import java.util.*;  
    4. /* 
    5.  * author:Tammy Pi 
    6.  * function:爬取器命令行运行 
    7.  * Email:victory_pj@163.com 
    8.  */  
    9. public class CrawlerHelper {  
    10.   
    11.     public boolean doCrawler(String path,String username) {  
    12.           
    13.         FetcherHelper fetcherHelper = new FetcherHelper();  
    14.         String html = fetcherHelper.getPageContent(path);  
    15.         if(html.equals("")){  
    16.               
    17.             return false;  
    18.         }  
    19.         List<com.BlogCrawler.Model.Document> list = null;  
    20.           
    21.         if(html.indexOf("postTitle")==-1){  
    22.               
    23.             list = fetcherHelper.htmlFilter(html,"div","class","post");  
    24.         }else{  
    25.               
    26.             list = fetcherHelper.htmlFilter(html,"div","class","postTitle");  
    27.         }  
    28.           
    29.         DocHelper docHelper = new DocHelper();  
    30.         docHelper.docHelper(username+".doc", list);  
    31.           
    32.         return true;  
    33.     }  
    34.       
    35.     public static void main(String[] args){  
    36.           
    37.         Scanner scan = new Scanner(System.in);  
    38.         System.out.println("请输入博客地址:");  
    39.         String path = scan.nextLine();  
    40.         System.out.println("请输入用户名:");  
    41.         String username = scan.nextLine();  
    42.           
    43.         CrawlerHelper helper = new CrawlerHelper();  
    44.         int index = 1;  
    45.           
    46.         helper.doCrawler(path, username);  
    47.         System.out.println("写入完成。文档位于c:\\Blog下。");  
    48.     }  
    49. }  

    运行CrawlerHelper,运行效果为;

    请输入博客地址:
    http://www.cnblogs.com/passzh/
    请输入用户名:
    风清月明
    最近项目开发中需记住的一些经验
    JSP的URL页面传参乱码问题的解决
    Hibernate的使用
    比较重要的三个正则表达式(JAVA)
    JAVA中Map按照value值逆序排序
    MFC的列表控件的使用
    MFC中TAB控件的使用
    MFC通过ADO连接MS SQLSERVER数据库
    不产生乱码的方法
    在Dreamweaver中建立JSP站点的方法
    写入完成。文档位于c:\Blog下。

    再看看你的C盘Blog文件夹下,是否有个“风清月明.doc”,这篇博客的本页内容,就被写入DOC文档了。大功告成!

    PS:对于有人在我的资源中评论说不能爬取的问题,我想说,我自己已经试验过了(首先,你写的地址必须是【博客园】的【具体的人的博客的地址】;其次,大概可以爬60%,有40%由于博客DOM结构没有分析到,所以爬取不了)。如果要用,请自行修改。

  • 相关阅读:
    支付相关备忘
    大文件跨服务器传送
    redis与memcache区别总结
    linux grep 查找字符串
    db2 连接报错connect。 ERRORCODE=-4499, SQLSTATE=08001(转载)
    linux查看匹配内容的前后几行(转)
    weblogic线程阻塞性能调优(图解)转
    ThreadPool has stuck threads
    Shell脚本中调用另外一个脚本的方法
    MUTT+MSMTP利用163服务器发送邮件
  • 原文地址:https://www.cnblogs.com/chenying99/p/2729912.html
Copyright © 2011-2022 走看看