Change Dir

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

          導(dǎo)航

          <2011年10月>
          2526272829301
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          公告

          寫下來的都是資源,分享給互聯(lián)網(wǎng)~~均屬原創(chuàng)隨筆。
          轉(zhuǎn)載引用請注明作者changedi。
          喜歡應(yīng)用研究,熱愛編程,歡迎交流。

          隨筆分類(125)

          隨筆檔案(123)

          統(tǒng)計(jì)

          留言簿(18)

          積分與排名

          “牛”們的博客

          各個(gè)公司技術(shù)

          我的鏈接

          淘寶技術(shù)

          閱讀排行榜

          評論排行榜

          工具包系列(1):htmlStat工具——統(tǒng)計(jì)頁面信息

          寫在前面:好久沒更新blog了,最近雖然比較閑,但是讀書和看報(bào)的時(shí)間占去了大半,又疏于總結(jié),一點(diǎn)點(diǎn)遺憾,好在補(bǔ)充的都是基礎(chǔ)~~

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

          先放上一些代碼:

          htmlStat主要想做什么,就是統(tǒng)計(jì)頁面的信息,我一直認(rèn)為頁面的結(jié)構(gòu)設(shè)計(jì)是設(shè)計(jì)人員按照思維套路來進(jìn)行的。數(shù)字往往反映了一個(gè)設(shè)計(jì)的一個(gè)很重要的方面,比如它使用的各個(gè)tag的比例,文字的數(shù)量,圖片的數(shù)量和大小等等。而想學(xué)習(xí)理解出這一套思路,先統(tǒng)計(jì)頁面信息是最重要的。

          當(dāng)然先說下開發(fā)環(huán)境:jdk1.6.11,maven2,git

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

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

          因?yàn)闀簳r(shí)第一版可以說沒什么復(fù)雜的結(jié)構(gòu)可言,我就直接上代碼了~

          這個(gè)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; // 存放所有標(biāo)簽的計(jì)數(shù)器
            42:  
            43:     private ExecutorService exec;
            44:  
            45:     private List<String> textList; // 存放文本數(shù)據(jù)的隊(duì)列
            46:  
            47:     private List<LinkObject> linkList; // 存放超鏈接對應(yīng)的文本
            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樹 統(tǒng)計(jì)全文的字?jǐn)?shù) 統(tǒng)計(jì)全文的標(biāo)簽總數(shù) 統(tǒng)計(jì)各類標(biāo)簽數(shù),統(tǒng)計(jì)資源放入一個(gè)map
            59:      * 當(dāng)發(fā)現(xiàn)有圖像標(biāo)記時(shí),可以將其放入一個(gè)隊(duì)列,然后開線程去預(yù)渲染圖片(只讀圖片頭) 圖片渲染完畢后,列出圖片的信息 統(tǒng)計(jì)全文的標(biāo)簽文字?jǐn)?shù),非空
            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("該頁有標(biāo)簽種類:");
           243:             System.out.println(hs.getStatMap().size());
           244:             System.out.println("有圖像標(biāo)簽:");
           245:             System.out.println(hs.getImageObjectList().size());
           246:             System.out.println("有文本標(biāo)簽:");
           247:             System.out.println(hs.getTextList().size());
           248:             System.out.println("有超鏈接標(biāo)簽");
           249:             System.out.println(hs.getLinkList().size());
           250:         } catch (Exception e) {
           251:             e.printStackTrace();
           252:         }
           253:     }
           254: }

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

          主要流程說一下:

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

          2. 遍歷html文檔的dom樹,依次將每個(gè)tag node存到數(shù)據(jù)結(jié)構(gòu)中

          3. 當(dāng)遇到圖片節(jié)點(diǎn)時(shí),開一個(gè)線程去讀取圖片頭,將其結(jié)構(gòu)信息存儲(chǔ)到對應(yīng)存儲(chǔ)結(jié)構(gòu)中

          4. 結(jié)束,訪問各個(gè)數(shù)據(jù)結(jié)構(gòu)得到統(tǒng)計(jì)信息

          這里列出訪問幾個(gè)大網(wǎng)站的一些獲取頁面信息

          taobao.com:

          該頁有標(biāo)簽種類:
          14
          有圖像標(biāo)簽:
          117
          有文本標(biāo)簽:
          313
          有超鏈接標(biāo)簽
          734

          qq.com:

          該頁有標(biāo)簽種類:
          15
          有圖像標(biāo)簽:
          51
          有文本標(biāo)簽:
          514
          有超鏈接標(biāo)簽
          762

          163.com:

          該頁有標(biāo)簽種類:
          16
          有圖像標(biāo)簽:
          114
          有文本標(biāo)簽:
          297
          有超鏈接標(biāo)簽
          1654

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

           

          下一步安排是一個(gè)imageCrawler~~圖片抓取器~~

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

          評論

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

          很好 很不錯(cuò)   回復(fù)  更多評論   

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

          看過。。  回復(fù)  更多評論   

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

          工具不錯(cuò)  回復(fù)  更多評論   

          主站蜘蛛池模板: 攀枝花市| 广州市| 冷水江市| 尤溪县| 台山市| 马边| 德保县| 无为县| 册亨县| 上思县| 哈巴河县| 武穴市| 建水县| 大石桥市| 黑水县| 库尔勒市| 静乐县| 西畴县| 金昌市| 龙胜| 兰州市| 延边| 彰化市| 文化| 简阳市| 眉山市| 佛冈县| 砀山县| 曲靖市| 兖州市| 宜黄县| 瑞安市| 湟中县| 龙门县| 平顺县| 望城县| 峨眉山市| 伽师县| 平和县| 电白县| 那坡县|