自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

微信公號開發(fā)實戰(zhàn)之歷史上的今天

移動開發(fā)
本篇文章主要講解如何在微信公眾帳號上實現(xiàn)“歷史上的今天”功能。這個例子本身并不復雜,但希望通過對它的學習,讀者能夠?qū)φ齽t表達式有一個新的認識,能夠?qū)W會運用現(xiàn)有的網(wǎng)絡資源豐富自己的公眾賬號。

本篇文章主要講解如何在微信公眾帳號上實現(xiàn)“歷史上的今天”功能。這個例子本身并不復雜,但希望通過對它的學習,讀者能夠?qū)φ齽t表達式有一個新的認識,能夠?qū)W會運用現(xiàn)有的網(wǎng)絡資源豐富自己的公眾賬號。

何謂歷史上的今天

回顧歷史的長河,歷史是生活的一面鏡子;以史為鑒,可以知興衰;歷史上的每一天,都是喜憂參半;可以了解歷史的這一天發(fā)生的事件,借古可以鑒今,歷史是不能忘記的。查看歷史上每天發(fā)生的重大事情,增長知識,開拓眼界,提高人文素養(yǎng)。

尋找接口(數(shù)據(jù)源)

要實現(xiàn)查詢“歷史上的今天”,首先我們要找到相關(guān)數(shù)據(jù)源。筆者經(jīng)過搜索發(fā)現(xiàn),網(wǎng)絡上幾乎沒有現(xiàn)成的“歷史上的今天”API可以使用,所以我們只能通過爬取、解析網(wǎng)頁源代碼的方式得到我們需要的數(shù)據(jù)。筆者發(fā)現(xiàn)網(wǎng)站http://www.rijiben.com/上包含“歷史上的今天”功能,就用它做數(shù)據(jù)源了。

開發(fā)步驟

為了便于讀者理解,我們需要清楚該應用實例的開發(fā)步驟,主要如下:

1)發(fā)起HTTP GET請求,獲取網(wǎng)頁源代碼。

2)運用正則表達式從網(wǎng)頁源代碼中抽取我們需要的數(shù)據(jù)。

3)對抽取得到的數(shù)據(jù)進行加工(使內(nèi)容呈現(xiàn)更加美觀)。

4)將以上三步進行封裝,供外部調(diào)用。

5)在公眾賬號后臺調(diào)用封裝好的“歷史上的今天”查詢方法。

代碼實現(xiàn)

筆者將上述步驟1)、2)、3)中的代碼實現(xiàn)封裝成了TodayInHistoryService類,并對外提供了getTodayInHistory()方法來獲取“歷史上的今天”。實現(xiàn)代碼如下:

  1. import java.io.BufferedReader; 
  2. import java.io.InputStream; 
  3. import java.io.InputStreamReader; 
  4. import java.net.HttpURLConnection; 
  5. import java.net.URL; 
  6. import java.text.DateFormat; 
  7. import java.text.SimpleDateFormat; 
  8. import java.util.Calendar; 
  9. import java.util.regex.Matcher; 
  10. import java.util.regex.Pattern; 
  11.  
  12. /** 
  13.  * 歷史上的今天查詢服務 
  14.  *  
  15.  * @author liufeng 
  16.  * @date 2013-10-16 
  17.  *  
  18.  */ 
  19. public class TodayInHistoryService { 
  20.  
  21.     /** 
  22.      * 發(fā)起http get請求獲取網(wǎng)頁源代碼 
  23.      *  
  24.      * @param requestUrl 
  25.      * @return 
  26.      */ 
  27.     private static String httpRequest(String requestUrl) { 
  28.         StringBuffer buffer = null
  29.  
  30.         try { 
  31.             // 建立連接 
  32.             URL url = new URL(requestUrl); 
  33.             HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection(); 
  34.             httpUrlConn.setDoInput(true); 
  35.             httpUrlConn.setRequestMethod("GET"); 
  36.  
  37.             // 獲取輸入流 
  38.             InputStream inputStream = httpUrlConn.getInputStream(); 
  39.             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); 
  40.             BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 
  41.  
  42.             // 讀取返回結(jié)果 
  43.             buffer = new StringBuffer(); 
  44.             String str = null
  45.             while ((str = bufferedReader.readLine()) != null) { 
  46.                 buffer.append(str); 
  47.             } 
  48.  
  49.             // 釋放資源 
  50.             bufferedReader.close(); 
  51.             inputStreamReader.close(); 
  52.             inputStream.close(); 
  53.             httpUrlConn.disconnect(); 
  54.         } catch (Exception e) { 
  55.             e.printStackTrace(); 
  56.         } 
  57.         return buffer.toString(); 
  58.     } 
  59.  
  60.     /** 
  61.      * 從html中抽取出歷史上的今天信息 
  62.      *  
  63.      * @param html 
  64.      * @return 
  65.      */ 
  66.     private static String extract(String html) { 
  67.         StringBuffer buffer = null
  68.         // 日期標簽:區(qū)分是昨天還是今天 
  69.         String dateTag = getMonthDay(0); 
  70.  
  71.         Pattern p = Pattern.compile("(.*)(<div class=\"listren\">)(.*?)(</div>)(.*)"); 
  72.         Matcher m = p.matcher(html); 
  73.         if (m.matches()) { 
  74.             buffer = new StringBuffer(); 
  75.             if (m.group(3).contains(getMonthDay(-1))) 
  76.                 dateTag = getMonthDay(-1); 
  77.  
  78.             // 拼裝標題 
  79.             buffer.append("≡≡ ").append("歷史上的").append(dateTag).append(" ≡≡").append("\n\n"); 
  80.  
  81.             // 抽取需要的數(shù)據(jù) 
  82.             for (String info : m.group(3).split("  ")) { 
  83.                 info = info.replace(dateTag, "").replace("(圖)""").replaceAll("</?[^>]+>""").trim(); 
  84.                 // 在每行末尾追加2個換行符 
  85.                 if (!"".equals(info)) { 
  86.                     buffer.append(info).append("\n\n"); 
  87.                 } 
  88.             } 
  89.         } 
  90.         // 將buffer最后兩個換行符移除并返回 
  91.         return (null == buffer) ? null : buffer.substring(0, buffer.lastIndexOf("\n\n")); 
  92.     } 
  93.  
  94.     /** 
  95.      * 獲取前/后n天日期(M月d日) 
  96.      *  
  97.      * @return 
  98.      */ 
  99.     private static String getMonthDay(int diff) { 
  100.         DateFormat df = new SimpleDateFormat("M月d日"); 
  101.         Calendar c = Calendar.getInstance(); 
  102.         c.add(Calendar.DAY_OF_YEAR, diff); 
  103.         return df.format(c.getTime()); 
  104.     } 
  105.  
  106.     /** 
  107.      * 封裝歷史上的今天查詢方法,供外部調(diào)用 
  108.      *  
  109.      * @return 
  110.      */ 
  111.     public static String getTodayInHistoryInfo() { 
  112.         // 獲取網(wǎng)頁源代碼 
  113.         String html = httpRequest("http://www.rijiben.com/"); 
  114.         // 從網(wǎng)頁中抽取信息 
  115.         String result = extract(html); 
  116.  
  117.         return result; 
  118.     } 
  119.  
  120.     /** 
  121.      * 通過main在本地測試 
  122.      *  
  123.      * @param args 
  124.      */ 
  125.     public static void main(String[] args) { 
  126.         String info = getTodayInHistoryInfo(); 
  127.         System.out.println(info); 
  128.     } 

代碼解讀:

1)27-58行代碼是httpRequest()方法,用于發(fā)起http get請求,獲取指定url的網(wǎng)頁源代碼。

2)66-92行代碼是extract()方法,運用正則表達式從網(wǎng)頁源代碼中抽取“歷史上的今天”數(shù)據(jù)。

3)111-118行代碼是getTodayInHistory()方法,封裝給外部調(diào)用查詢“歷史上的今天”。

4)125-128行代碼是main方法,用于在本地的開發(fā)工具中測試。

5)75-76行代碼的作用是判斷獲取到的“歷史上的今天”數(shù)據(jù)是當天的還是前一天的(因為不能保證www.rijiben.com上的數(shù)據(jù)一定在凌晨零點準時更新,所以為了保證數(shù)據(jù)的準確性必須做此判斷)。

6)第71行代碼是本文的重點,筆者編寫的正則表達式規(guī)則是“(.*)(<div class=\"listren\">)(.*?)(</div>)(.*)”。正則表達式規(guī)則需要根據(jù)網(wǎng)頁源代碼進行編寫的,特別是包含“歷史上的今天”數(shù)據(jù)的那部分HTML標簽,所以我們先來查看網(wǎng)頁源代碼。通過httpRequest("http://www.rijiben.com/")方法獲取到的網(wǎng)頁源代碼,與我們通過瀏覽器訪問http://www.rijiben.com/頁面再點擊右鍵選擇“查看網(wǎng)頁源代碼”所得到的結(jié)果完全一致。我們通過瀏覽器查看http://www.rijiben.com/的網(wǎng)頁源代碼,然后找到“歷史上的今天”數(shù)據(jù)所在位置,如下圖所示:

從上面的源代碼截圖中可以看到,我們需要的數(shù)據(jù)被包含在<div class="listren">標簽內(nèi),這樣就不難理解為什么正則表達式要這樣寫:

(.*)(<div class=\"listren\">)(.*?)(</div>)(.*)

我們使用括號()將正則表達式規(guī)則分成了5組,下面是這些分組的說明:

  • 第1組:(.*)表示網(wǎng)頁源代碼中<div class="listren">標簽之前還有任意多個字符。
  • 第2組:(<div class=\"listren\">)中的反斜杠表示轉(zhuǎn)義,所以該規(guī)則就是用于匹配<div class="listren">。
  • 第3組:(.*?)表示在標簽<div class="listren">和</div>之間的所有內(nèi)容,這才是我們真正需要的數(shù)據(jù)所在。
  • 第4組:(</div>)就是用于匹配<div class="listren">的結(jié)束標簽。
  • 第5組:(.*)表示在</div>標簽之后還有任意多的字符。

掌握了正則表達式規(guī)則的含義,就不難理解為什么在extract()方法中全都是在使用m.group(3),因為m.group(3)就表示匹配到數(shù)據(jù)的第3個分組。m.group(3)的內(nèi)容如下:

  1. <ul>                      <li><a href="/news6836/" title="0690年10月16日 武則天登上皇位">0690年10月16日 武則天登上皇位</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6837/" title="1854年10月16日 唯美主義運動的倡導者王爾德誕辰">1854年10月16日 唯美主義運動的倡導者王爾德誕辰</a>&nbsp;&nbsp;</li>                      <li><a href="/news6838/" title="1854年10月16日 德國社會主義活動家考茨基誕生">1854年10月16日 德國社會主義活動家考茨基誕生</a>&nbsp;&nbsp;</li>                      <li><a href="/news6839/" title="1908年10月16日 阿爾巴尼亞領(lǐng)導人恩維爾·霍查誕辰">1908年10月16日 阿爾巴尼亞領(lǐng)導人恩維爾·霍查誕辰</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6840/" title="1913年10月16日 中國“兩彈一星”元勛錢三強誕辰">1913年10月16日 中國“兩彈一星”元勛錢三強誕辰</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6841/" title="1922年10月16日 開灤煤礦工人罷工失敗">1922年10月16日 開灤煤礦工人罷工失敗</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6842/" title="1927年10月16日 德國諾貝爾文學獎得主格拉斯誕生">1927年10月16日 德國諾貝爾文學獎得主格拉斯誕生</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6843/" title="1933年10月16日 抗日同盟軍失敗">1933年10月16日 抗日同盟軍失敗</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6844/" title="1950年10月16日 人民解放軍進軍西藏">1950年10月16日 人民解放軍進軍西藏</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6845/" title="1954年10月16日 俞平伯《關(guān)于紅樓夢研究問題的信》發(fā)表">1954年10月16日 俞平伯《關(guān)于紅樓夢研究問題的信》發(fā)表</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6846/" title="1959年10月16日 美軍將領(lǐng)、國務卿馬歇爾去世">1959年10月16日 美軍將領(lǐng)、國務卿馬歇爾去世</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6847/" title="1964年10月16日 勃列日涅夫取代赫魯曉夫  成為蘇共中央第一書記">1964年10月16日 勃列日涅夫取代赫魯曉夫  成為蘇共中央第一書記</a>&nbsp;&nbsp;</li>                      <li><a href="/news6848/" title="1964年10月16日 我國第一顆原子彈爆炸成功">1964年10月16日 我國第一顆原子彈爆炸成功</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6849/" title="1973年10月16日 震撼世界的石油危機爆發(fā)">1973年10月16日 震撼世界的石油危機爆發(fā)</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6850/" title="1978年10月16日 約翰·保羅二世當選新教皇">1978年10月16日 約翰·保羅二世當選新教皇</a>&nbsp;&nbsp;</li>                      <li><a href="/news6851/" title="1979年10月16日 哈克將軍宣布巴基斯坦推遲大選解散政黨">1979年10月16日 哈克將軍宣布巴基斯坦推遲大選解散政黨</a>&nbsp;&nbsp;</li>                      <li><a href="/news6852/" title="1984年10月16日 圖圖主教榮獲“諾貝爾和平獎”">1984年10月16日 圖圖主教榮獲“諾貝爾和平獎”</a>&nbsp;&nbsp;</li>                      <li><a href="/news6853/" title="1988年10月16日 北京正負電子對撞機對撞成功">1988年10月16日 北京正負電子對撞機對撞成功</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6854/" title="1991年10月16日 美國小鎮(zhèn)槍殺案22人喪生">1991年10月16日 美國小鎮(zhèn)槍殺案22人喪生</a>&nbsp;&nbsp;</li>                      <li><a href="/news6855/" title="1991年10月16日 莫扎特死因有新說">1991年10月16日 莫扎特死因有新說</a>&nbsp;&nbsp;</li>                      <li><a href="/news6856/" title="1991年10月16日 錢學森獲“國家杰出貢獻科學家”殊榮">1991年10月16日 錢學森獲“國家杰出貢獻科學家”殊榮</a>&nbsp;&nbsp;(圖)</li>                      <li><a href="/news6857/" title="1994年10月16日 德國總理科爾四連任">1994年10月16日 德國總理科爾四連任</a>&nbsp;&nbsp;</li>                      <li><a href="/news6858/" title="1994年10月16日 第十二屆廣島亞運會閉幕">1994年10月16日 第十二屆廣島亞運會閉幕</a>&nbsp;&nbsp;</li>                      <li><a href="/news6859/" title="1994年10月16日 修秦陵制秦俑工匠墓葬被發(fā)現(xiàn)">1994年10月16日 修秦陵制秦俑工匠墓葬被發(fā)現(xiàn)</a>&nbsp;&nbsp;</li>                      <li><a href="/news6860/" title="1995年10月16日 美國百萬黑人男子大游行">1995年10月16日 美國百萬黑人男子大游行</a>&nbsp;&nbsp;(圖)</li>                    </ul>        

可以看到,通過正則表達式抽取得到的m.group(3)中仍然有大量的html標簽、空格、換行、無關(guān)字符等。我們要想辦法把它們?nèi)窟^濾掉,第83行代碼的作用正是如此。

組裝文本消息

  1. // 組裝文本消息(歷史上的今天) 
  2. TextMessage textMessage = new TextMessage(); 
  3. textMessage.setToUserName(fromUserName); 
  4. textMessage.setFromUserName(toUserName); 
  5. textMessage.setCreateTime(new Date().getTime()); 
  6. textMessage.setMsgType(WeixinUtil.RESP_MESSAGE_TYPE_TEXT); 
  7. textMessage.setFuncFlag(0); 
  8. textMessage.setContent(TodayInHistoryService.getTodayInHistoryInfo()); 

效果示例:

說明:與其說這是一篇關(guān)于公眾帳號應用開發(fā)的教程,倒不如說這是一篇關(guān)于網(wǎng)頁數(shù)據(jù)爬取的教程。本文旨在為讀者開辟思路,介紹一種數(shù)據(jù)獲取方式。當然,這種做法也是有弊端的,當網(wǎng)頁改版源代碼結(jié)構(gòu)發(fā)生變化時,就需要重新改寫數(shù)據(jù)抽取代碼。

責任編輯:徐川 來源: blog
相關(guān)推薦

2013-11-13 01:25:33

微信微信公號微信公眾賬號

2013-11-13 00:14:16

微信微信公號微信公眾賬號

2013-11-13 00:51:22

微信微信公號微信公眾賬號

2013-11-13 00:37:12

微信微信公號微信公眾賬號

2012-01-12 14:06:34

2013-11-12 23:32:53

微信公號微信公眾賬號

2013-09-09 16:38:01

諾基亞微軟

2013-11-13 00:20:01

微信微信公號微信公眾賬號

2010-09-15 08:59:04

開源交易

2011-07-01 10:20:32

2023-12-19 11:22:05

2024-03-19 08:00:00

測試漏洞

2023-10-26 00:07:04

2017-07-28 10:55:49

AITayAlexa

2015-12-25 11:34:25

2023-11-27 15:03:26

2012-11-13 10:32:22

2011-03-16 10:00:46

2015-06-08 09:46:04

2014-09-24 11:32:21

微信企業(yè)號開發(fā)
點贊
收藏

51CTO技術(shù)棧公眾號