Change Dir

          先知cd——熱愛生活是一切藝術的開始

          統計

          留言簿(18)

          積分與排名

          “牛”們的博客

          各個公司技術

          我的鏈接

          淘寶技術

          閱讀排行榜

          評論排行榜

          工具包系列(1):htmlStat工具——統計頁面信息

          寫在前面:好久沒更新blog了,最近雖然比較閑,但是讀書和看報的時間占去了大半,又疏于總結,一點點遺憾,好在補充的都是基礎~~

          最近準備開一個git庫做開源的工具庫,也許是reinvent wheels,但是覺得能對自己工作有幫助。畢竟熟悉運用比較方便。

          先放上一些代碼:

          htmlStat主要想做什么,就是統計頁面的信息,我一直認為頁面的結構設計是設計人員按照思維套路來進行的。數字往往反映了一個設計的一個很重要的方面,比如它使用的各個tag的比例,文字的數量,圖片的數量和大小等等。而想學習理解出這一套思路,先統計頁面信息是最重要的。

          當然先說下開發環境:jdk1.6.11,maven2,git

          主要的依賴目前只在pom中更新了一部分,有加入的會慢慢加入,具體可以看github上的項目信息

          有愿意一起玩代碼的,可以留言我,

          因為暫時第一版可以說沒什么復雜的結構可言,我就直接上代碼了~

          這個htmlstat是主類

             1: /**
             2:  * 
             3:  */
             4: package com.taobao.cd.http.util;
             5:  
             6: import java.io.IOException;
             7: import java.io.InputStream;
             8: import java.net.URL;
             9: import java.net.URLConnection;
            10: import java.util.ArrayList;
            11: import java.util.HashMap;
            12: import java.util.List;
            13: import java.util.concurrent.Callable;
            14: import java.util.concurrent.ExecutionException;
            15: import java.util.concurrent.ExecutorService;
            16: import java.util.concurrent.Executors;
            17: import java.util.concurrent.FutureTask;
            18:  
            19: import javax.imageio.ImageIO;
            20: import javax.imageio.ImageReader;
            21: import javax.imageio.stream.ImageInputStream;
            22:  
            23: import org.htmlparser.Node;
            24: import org.htmlparser.NodeFilter;
            25: import org.htmlparser.Parser;
            26: import org.htmlparser.Tag;
            27: import org.htmlparser.Text;
            28: import org.htmlparser.filters.TagNameFilter;
            29: import org.htmlparser.tags.ImageTag;
            30: import org.htmlparser.tags.LinkTag;
            31: import org.htmlparser.util.NodeList;
            32: import org.htmlparser.util.ParserException;
            33:  
            34: /**
            35:  * @author zunyuan.jy
            36:  * 
            37:  * @date 2011-10-25
            38:  */
            39: public class HtmlStat {
            40:  
            41:     private HashMap<Class<? extends Node>, Integer> statMap; // 存放所有標簽的計數器
            42:  
            43:     private ExecutorService exec;
            44:  
            45:     private List<String> textList; // 存放文本數據的隊列
            46:  
            47:     private List<LinkObject> linkList; // 存放超鏈接對應的文本
            48:  
            49:     private List<ImageObject> imageObjectList; // 存放處理完后的圖像信息
            50:  
            51:     private Parser parser;
            52:  
            53:     private ParserPool parserPool;
            54:  
            55:     private String host;
            56:  
            57:     /**
            58:      * 先序遍歷dom樹 統計全文的字數 統計全文的標簽總數 統計各類標簽數,統計資源放入一個map
            59:      * 當發現有圖像標記時,可以將其放入一個隊列,然后開線程去預渲染圖片(只讀圖片頭) 圖片渲染完畢后,列出圖片的信息 統計全文的標簽文字數,非空
            60:      * 
            61:      * @throws IOException
            62:      * @throws ParserException
            63:      * 
            64:      */
            65:  
            66:     public HtmlStat() {
            67:         parserPool = ParserPool.getInstance();
            68:         textList = new ArrayList<String>(20);
            69:         linkList = new ArrayList<LinkObject>(20);
            70:         imageObjectList = new ArrayList<ImageObject>(20);
            71:         statMap = new HashMap<Class<? extends Node>, Integer>(100);
            72:     }
            73:  
            74:     private void createParser(String url) throws Exception {
            75:         URL u = new URL(url);
            76:         host = u.getProtocol() + "://" + u.getHost();
            77:         URLConnection con = u.openConnection();
            78:         con.setRequestProperty("User-Agent", HttpUtil.UA);
            79:         org.htmlparser.scanners.ScriptScanner.STRICT = false;
            80:         org.htmlparser.lexer.Lexer.STRICT_REMARKS = false;
            81:         parser = parserPool.borrowOne();
            82:         parser.setConnection(con);
            83:     }
            84:  
            85:     public void analyse(String url) throws Exception {
            86:         createParser(url);
            87:         exec = Executors.newCachedThreadPool();
            88:  
            89:         parse();
            90:  
            91:         exec.shutdown();
            92:         returnParser();
            93:     }
            94:  
            95:     private void parse() throws ParserException {
            96:         NodeFilter filter = new TagNameFilter("body");
            97:         NodeList nodes = parser.extractAllNodesThatMatch(filter);
            98:         Node node = null;
            99:         if (nodes != null) {
           100:             for (int i = 0; i < nodes.size(); i++) {
           101:                 node = nodes.elementAt(i);
           102:                 recursiveParse(node);
           103:             }
           104:         }
           105:     }
           106:  
           107:     private void recursiveParse(Node node) {
           108:         if (node != null) {
           109:             NodeList nodes = node.getChildren();
           110:             Node tNode = null;
           111:             if (nodes != null) {
           112:                 for (int i = 0; i < nodes.size(); i++) {
           113:                     tNode = nodes.elementAt(i);
           114:                     if (tNode instanceof Text) {
           115:                         if (tNode.toPlainTextString().trim().equals(""))
           116:                             continue;
           117:                         if (node instanceof LinkTag) {
           118:                             LinkTag aTag = (LinkTag) node;
           119:                             if (aTag.isHTTPLink()
           120:                                     && aTag.getAttribute("href") != null) {
           121:                                 String link = aTag.getAttribute("href");
           122:                                 LinkObject lo = new LinkObject();
           123:                                 lo.setLink(link);
           124:                                 lo.setText(tNode.toPlainTextString().trim());
           125:                                 linkList.add(lo);
           126:                             }
           127:                         } else {
           128:                             textList.add(tNode.toPlainTextString().trim());
           129:                         }
           130:                         /*
           131:                          * if (node instanceof LinkTag) { LinkTag aTag =
           132:                          * (LinkTag) node; if (aTag.isHTTPLink() &&
           133:                          * aTag.getAttribute("href") != null){ String link =
           134:                          * aTag.getAttribute("href"); } } else if (node
           135:                          * instanceof Div) {
           136:                          * 
           137:                          * } else if (node instanceof TableTag || node
           138:                          * instanceof TableHeader) {
           139:                          * 
           140:                          * } else if (node instanceof TableRow || node
           141:                          * instanceof TableColumn) {
           142:                          * 
           143:                          * } else if (node instanceof ParagraphTag) {
           144:                          * 
           145:                          * } else if (node instanceof DefinitionListBullet) {
           146:                          * 
           147:                          * } else if (node instanceof BulletList) {
           148:                          * 
           149:                          * } else if (node instanceof Span) {
           150:                          * 
           151:                          * } else if (node instanceof HeadingTag) {
           152:                          * 
           153:                          * }
           154:                          */
           155:                     } else if (tNode instanceof ImageTag) {
           156:                         ImageTag img = (ImageTag) tNode;
           157:                         String url = img.getImageURL();
           158:                         if (!url.startsWith("http://")
           159:                                 && !url.startsWith("https://")) {
           160:                             url = host + url;
           161:                         }
           162:                         final String imgSrc = url;
           163:                         final String alt = img.getAttribute("alt");
           164:                         FutureTask<ImageObject> task = new FutureTask<ImageObject>(
           165:                                 new Callable<ImageObject>() {
           166:  
           167:                                     public ImageObject call() throws Exception {
           168:                                         // TODO Auto-generated method stub
           169:                                         URL u = new URL(imgSrc);
           170:                                         String suffix = imgSrc.substring(imgSrc
           171:                                                 .lastIndexOf(".") + 1);
           172:                                         InputStream is = u.openStream();
           173:                                         ImageInputStream stream = ImageIO
           174:                                                 .createImageInputStream(is);
           175:                                         ImageReader ir = ImageReaderFactory
           176:                                                 .getInstance()
           177:                                                 .createImageReader(suffix);
           178:                                         ImageObject io = new ImageObject();
           179:                                         if (ir != null) {
           180:                                             ir.setInput(stream, true, false);
           181:                                             int w = ir.getWidth(0);
           182:                                             int h = ir.getHeight(0);
           183:  
           184:                                             io.setUrl(imgSrc);
           185:                                             io.setWidth(w);
           186:                                             io.setHeight(h);
           187:                                             io.setFormat(suffix);
           188:                                             io.setAlt(alt);
           189:  
           190:                                         }
           191:                                         return io;
           192:                                     }
           193:  
           194:                                 });
           195:                         try {
           196:                             exec.execute(task);
           197:                             imageObjectList.add(task.get());
           198:                         } catch (InterruptedException e) {
           199:                             e.printStackTrace();
           200:                         } catch (ExecutionException e) {
           201:                             e.printStackTrace();
           202:                         }
           203:  
           204:                     } else if (tNode instanceof Tag) {
           205:                         int x = 1;
           206:                         if (statMap.containsKey(tNode.getClass())) {
           207:                             x = statMap.get(tNode.getClass());
           208:                             x++;
           209:                         }
           210:                         statMap.put(tNode.getClass(), x);
           211:                         recursiveParse(tNode);
           212:                     }
           213:                 }
           214:             }
           215:         }
           216:     }
           217:  
           218:     private void returnParser() throws Exception {
           219:         parserPool.returnOne(parser);
           220:     }
           221:  
           222:     public HashMap<Class<? extends Node>, Integer> getStatMap() {
           223:         return statMap;
           224:     }
           225:  
           226:     public List<String> getTextList() {
           227:         return textList;
           228:     }
           229:  
           230:     public List<LinkObject> getLinkList() {
           231:         return linkList;
           232:     }
           233:  
           234:     public List<ImageObject> getImageObjectList() {
           235:         return imageObjectList;
           236:     }
           237:  
           238:     public static void main(String[] args) {
           239:         HtmlStat hs = new HtmlStat();
           240:         try {
           241:             hs.analyse("http://163.com");
           242:             System.out.println("該頁有標簽種類:");
           243:             System.out.println(hs.getStatMap().size());
           244:             System.out.println("有圖像標簽:");
           245:             System.out.println(hs.getImageObjectList().size());
           246:             System.out.println("有文本標簽:");
           247:             System.out.println(hs.getTextList().size());
           248:             System.out.println("有超鏈接標簽");
           249:             System.out.println(hs.getLinkList().size());
           250:         } catch (Exception e) {
           251:             e.printStackTrace();
           252:         }
           253:     }
           254: }

          其中用到的imageObject和linkObject就是兩個POJO。對于圖片的處理,用到了一個imageReaderFactory,對于解析器parser的管理用到了對象池。目前還都是非常簡單的版本。

          主要流程說一下:

          1. 建立連接器和parser解析html

          2. 遍歷html文檔的dom樹,依次將每個tag node存到數據結構中

          3. 當遇到圖片節點時,開一個線程去讀取圖片頭,將其結構信息存儲到對應存儲結構中

          4. 結束,訪問各個數據結構得到統計信息

          這里列出訪問幾個大網站的一些獲取頁面信息

          taobao.com:

          該頁有標簽種類:
          14
          有圖像標簽:
          117
          有文本標簽:
          313
          有超鏈接標簽
          734

          qq.com:

          該頁有標簽種類:
          15
          有圖像標簽:
          51
          有文本標簽:
          514
          有超鏈接標簽
          762

          163.com:

          該頁有標簽種類:
          16
          有圖像標簽:
          114
          有文本標簽:
          297
          有超鏈接標簽
          1654

          P.S. 我會逐漸增加一些通用的代碼到這個庫中,慢慢將其做好做完善,主要涉及的方向是數學、算法、html解析和一些通用操作。感興趣的同學可以發郵件或者直接留言。我們一起將這個library建設的更強大更健壯。代碼地址在這里git://github.com/changedi/CDLib.git

           

          下一步安排是一個imageCrawler~~圖片抓取器~~

          posted on 2011-10-31 13:28 changedi 閱讀(2127) 評論(3)  編輯  收藏 所屬分類: Java技術

          評論

          # re: 工具包系列(1):htmlStat工具&mdash;&mdash;統計頁面信息 2011-11-04 08:26 tbw淘寶

          很好 很不錯   回復  更多評論   

          # re: 工具包系列(1):htmlStat工具&mdash;&mdash;統計頁面信息 2011-11-08 20:12 秋楓訣

          看過。。  回復  更多評論   

          # re: 工具包系列(1):htmlStat工具&mdash;&mdash;統計頁面信息 2011-11-11 13:46 tbw淘寶

          工具不錯  回復  更多評論   

          主站蜘蛛池模板: 宝清县| 望奎县| 深泽县| 定州市| 西昌市| 广饶县| 赤峰市| 台南县| 林州市| 洛浦县| 同江市| 南充市| 正蓝旗| 永丰县| 老河口市| 灵丘县| 东台市| 英吉沙县| 金秀| 博客| 佛教| 蒙自县| 中西区| 大港区| 贞丰县| 道孚县| 安吉县| 历史| 福海县| 嘉禾县| 泰州市| 和顺县| 邛崃市| 体育| 许昌市| 门源| 清河县| 湖口县| 惠州市| 沾益县| 阿拉善右旗|