隨筆 - 170  文章 - 536  trackbacks - 0
          <2007年6月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          1234567

          常用鏈接

          我參與的團(tuán)隊(duì)

          隨筆分類(103)

          搜索

          •  

          積分與排名

          • 積分 - 415111
          • 排名 - 135

          最新評(píng)論

          閱讀排行榜

          上一篇中我們說(shuō)到了,如何使用 HttpClient 抓取所需要的數(shù)據(jù),接下來(lái)介紹一下如何對(duì)這些數(shù)據(jù)進(jìn)行處理。基本的處理原理是使用正則表達(dá)式進(jìn)行內(nèi)容的匹配。

          為了便于處理,我們首先把使用 HttpClient 抓取到的數(shù)據(jù)做一些簡(jiǎn)單的處理。

          第一步要做的就是刪除回車符,當(dāng)然我不會(huì)寫含有回車符的正則表達(dá)式才會(huì)這么寫的,當(dāng)然如果您有更好的方法也可以不用這么做。

          代碼很簡(jiǎn)單:

          1protected String removeEnter(String response) {
          2    response = StringUtils.replace(response, "\r\n""");
          3    response = StringUtils.replace(response, "\n""");
          4    return response;
          5}

          接下來(lái)就可以使用正則表達(dá)式來(lái)對(duì)所抓取的內(nèi)容進(jìn)行匹配了:

          正則表達(dá)式是一種可以用于模式匹配和替換的強(qiáng)有力的工具,一個(gè)正則表達(dá)式就是由普通的字符(例如字符 a 到 z)以及特殊字符(稱為元字符)組成的文字模式,它描述在查找文字主體時(shí)待匹配的一個(gè)或多個(gè)字符串。正則表達(dá)式作為一個(gè)模板,將某個(gè)字符模式與所搜索的字符串進(jìn)行匹配。正則表達(dá)式在字符數(shù)據(jù)處理中起著非常重要的作用,我們可以用正則表達(dá)式完成大部分的數(shù)據(jù)分析處理工作,如:判斷一個(gè)串是否是數(shù)字、是否是有效的Email地址,從海量的文字資料中提取有價(jià)值的數(shù)據(jù)等等,如果不使用正則表達(dá)式,那么實(shí)現(xiàn)的程序可能會(huì)很長(zhǎng),并且容易出錯(cuò)。對(duì)這點(diǎn)本人深有體會(huì),面對(duì)大量工具書電子檔資料的整理工作,如果不懂得應(yīng)用正則表達(dá)式來(lái)處理,那么將是很痛苦的一件事情,反之則將可以輕松地完成,獲得事半功倍的效果。

          在這里,我使用了 Jakarta-ORO 作為正則表達(dá)式工具來(lái)進(jìn)行匹配。

          Jakarta-ORO是最全面以及優(yōu)化得最好的正則表達(dá)式API之一,Jakarta-ORO庫(kù)以前叫做OROMatcher,是由Daniel F. Savarese編寫,后來(lái)他將其贈(zèng)與Jakarta Project,讀者可在jakarta.apache.org的網(wǎng)站下載該API包。
          因?yàn)樵谶@里我們不需要用到太多正則表達(dá)式的知識(shí),僅僅是簡(jiǎn)單的用用而已,所以幾行簡(jiǎn)單的代碼就可以解決問(wèn)題:
          protected String match(String response, String template, int index) {
              Perl5Util engine 
          = new Perl5Util();
              String name 
          = null;
              
          if (response != null{
                  
          if (engine.match(template, response)) {
                      name 
          = engine.group(index);
                  }

              }

              
          return name;
          }

          第一個(gè)參數(shù) response 表示抓取到的頁(yè)面源碼,第二個(gè)參數(shù) template 表示我們預(yù)先設(shè)定的模板,第三個(gè)表示第幾個(gè)匹配。返回的結(jié)果是匹配成功的 group 中的內(nèi)容。

          于是我們可以這樣的調(diào)用它:

          String template = "/(滬綜指)</font></b></a> <span id=\"STK1\">(\\d{4,5}\\.\\d{1,4})</span>";
          String name 
          =  match(response, template, 1);
          String index 
          =  match(response, template, 2);

          注意一下,我們正則表達(dá)式前后都有 "/"。
          另外,我們用() 括起來(lái)的部分表示我們要匹配的內(nèi)容,所以這里 name 可以匹配到 滬綜指,index 可以匹配到大盤的點(diǎn)數(shù)。 

          該匹配對(duì)應(yīng)于: http://web7.jrj.com/homev1/StockIndex.htm
          為了防止頁(yè)面以后打不開了大家找不到,我把其中相關(guān)的匹配部分的頁(yè)面源碼也發(fā)出來(lái):

          <href=javascript:ShowImg('000001',2) target=_self><b><font color=#000000>滬綜指</font></b></a> <span id="STK1">3914.20</span> <span id="STK2" class="c1"><img src=/HomeV1/images/down.gif width=8 height=8>164.40</span> <href=javascript:ShowImg('399001',1) target=_self><b><font color=#000000>深成指</font></b></a> <span id="STK3">12882.17</span> <span id="STK4" class="c1"><img src=/HomeV1/images/down.gif width=8 height=8>701.53</span> <href=javascript:ShowImg('399300',1) target=_self><b><font color=#000000>滬深300</font></b></a> <span id="STK5">3858.52</span> <span id="STK6" class="c1"><img src=/HomeV1/images/down.gif width=8 height=8>181.96</span> <b>香港恒生</b> <span id="STK7">21938.22</span> <span id="STK8" class="c3"><img src=/HomeV1/images/up.gif width=8 height=8>232.66</span> <b>道瓊斯</b> <span id="STK9">13414.48</span> <span id="STK10" class="c1"><img src=/HomeV1/images/down.gif width=8 height=8>13.25</span> <b>納斯達(dá)克</b> <span id="STK11">2612.02</span> <span id="STK12" class="c3"><img src=/HomeV1/images/up.gif width=8 height=8>6.67</span> 
          <div id="indexdata"><object id="STKData" width="0" height="0" classid="CLSID:333C7BC4-460F-11D0-BC04-0080C7055A83" viewastext><param name="FieldDelim" value="F"><param name="DataURL" value="/HomeV1/text/StockIndex.htm"><param name="UseHeader" value="true"></object><input type="hidden" id="STKValue" datasrc="#STKData" datafld="a" name="STKValue"></div>

          因?yàn)槲也皇菫榱私榻B正則表達(dá)式而寫這篇文章的,所以對(duì)正則表達(dá)式不會(huì)做太多的介紹,如果大家對(duì)正則表達(dá)式有興趣或想進(jìn)一步了解的話可以參考:

          JAVA中正則表達(dá)式的應(yīng)用
          http://www.ibm.com/developerworks/cn/java/l-regp/part1/index.html
          http://www.ibm.com/developerworks/cn/java/l-regp/part2/index.html


          另外因?yàn)闉榱俗ト∑渌麞|西,代碼已經(jīng)被我改的面目全非了,暫時(shí)就不方便貼出來(lái)了,請(qǐng)大家諒解,如果大家有什么疑問(wèn)的話可以和我聯(lián)系,我會(huì)盡量說(shuō)明清楚的。
          posted on 2007-06-28 22:58 steady 閱讀(1799) 評(píng)論(2)  編輯  收藏 所屬分類: 技術(shù)隨筆

          FeedBack:
          # re: Java打造簡(jiǎn)易股指跟蹤系統(tǒng)(2) 2007-07-04 16:36 寒江
          剩下的只有定時(shí)抓取HTML源碼,然后使用正則匹配數(shù)據(jù)。復(fù)雜的通過(guò)htmlparser解析HTML,簡(jiǎn)單的可以通過(guò)正則過(guò)濾HTML標(biāo)簽 (\s*</?(\w+)(>|[^r][^>]*>)\s*)+|(&nbsp;)+|(\s)+ ,然后在進(jìn)行數(shù)據(jù)提取工作

          定時(shí)可以簡(jiǎn)單的在while(true)里放個(gè)Thread.currentThread().sleep(millis),而不必使用quartz 。

          不過(guò)老大寫出來(lái)沒幾天 ,印花稅就漲了。。。
          感覺老大還是很會(huì)理財(cái)?shù)?

          ORO木大用過(guò),似乎靜態(tài)的 java.util.regex.Pattern 變量更適合提升程序性能  回復(fù)  更多評(píng)論
            
          # re: Java打造簡(jiǎn)易股指跟蹤系統(tǒng)(2) 2007-07-05 00:21 steady
          @寒江
          我一般是 sleep(60000),也就是 60 秒。  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 报价| 弋阳县| 华池县| 洪洞县| 山西省| 贺州市| 临高县| 达日县| 关岭| 池州市| 黄陵县| 平利县| 承德县| 丰原市| 东莞市| 祁东县| 南江县| 莱西市| 新巴尔虎右旗| 天津市| 工布江达县| 阿拉善右旗| 扎兰屯市| 教育| 合山市| 大同市| 凤山县| 五常市| 望都县| 宁都县| 临沧市| 海安县| 来凤县| 互助| 莱州市| 保山市| 盘锦市| 玉山县| 青岛市| 中牟县| 佛坪县|