原文地址https://www.cnblogs.com/xiaoMzjm/p/3894805.html
【本文介紹】
爬取別人網頁上的內容,聽上似乎很有趣的樣子,只要幾步,就可以獲取到力所不能及的東西,例如呢?例如天氣預報,總不能自己拿着儀器去測吧!當然,要獲取天氣預報還是用webService好。這里只是舉個例子。話不多說了,上看看效果吧。
【效果】
我們隨便找個天氣預報的網站來試試:http://www.weather.com.cn/html/weather/101280101.shtml
從圖中可用看出,今天(6日)的天氣。我們就以這個為例,獲取今天的天氣吧!

最終后台打印出:
今天:6日 天氣:雷陣雨 溫度:26°~34° 風力:微風
【思路】
1、通過url獲取輸入流————2、獲取網頁html代碼————3、用正則表達式抽取有用的信息————4、拼裝成想要的格式
其實最難的一點事第3點,如果正則表示式不熟,基本上在這一步就會掛掉了——例如我T_T。下面為了抽取到正確的數據,我匹配了多次,如果能一次匹配的話,那代碼量就少多了!
【代碼】
1 package com.zjm.www.test;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.InputStreamReader;
7 import java.net.HttpURLConnection;
8 import java.net.URL;
9 import java.util.regex.Matcher;
10 import java.util.regex.Pattern;
11
12 /**
13 * 描述:趴取網頁上的今天的天氣
14 * @author zjm
15 * @time 2014/8/6
16 */
17 public class TodayTemperatureService {
18
19 /**
20 * 發起http get請求獲取網頁源代碼
21 * @param requestUrl String 請求地址
22 * @return String 該地址返回的html字符串
23 */
24 private static String httpRequest(String requestUrl) {
25
26 StringBuffer buffer = null;
27 BufferedReader bufferedReader = null;
28 InputStreamReader inputStreamReader = null;
29 InputStream inputStream = null;
30 HttpURLConnection httpUrlConn = null;
31
32 try {
33 // 建立get請求
34 URL url = new URL(requestUrl);
35 httpUrlConn = (HttpURLConnection) url.openConnection();
36 httpUrlConn.setDoInput(true);
37 httpUrlConn.setRequestMethod("GET");
38
39 // 獲取輸入流
40 inputStream = httpUrlConn.getInputStream();
41 inputStreamReader = new InputStreamReader(inputStream, "utf-8");
42 bufferedReader = new BufferedReader(inputStreamReader);
43
44 // 從輸入流讀取結果
45 buffer = new StringBuffer();
46 String str = null;
47 while ((str = bufferedReader.readLine()) != null) {
48 buffer.append(str);
49 }
50
51 } catch (Exception e) {
52 e.printStackTrace();
53 } finally {
54 // 釋放資源
55 if(bufferedReader != null) {
56 try {
57 bufferedReader.close();
58 } catch (IOException e) {
59 e.printStackTrace();
60 }
61 }
62 if(inputStreamReader != null){
63 try {
64 inputStreamReader.close();
65 } catch (IOException e) {
66 e.printStackTrace();
67 }
68 }
69 if(inputStream != null){
70 try {
71 inputStream.close();
72 } catch (IOException e) {
73 e.printStackTrace();
74 }
75 }
76 if(httpUrlConn != null){
77 httpUrlConn.disconnect();
78 }
79 }
80 return buffer.toString();
81 }
82
83 /**
84 * 過濾掉html字符串中無用的信息
85 * @param html String html字符串
86 * @return String 有用的數據
87 */
88 private static String htmlFiter(String html) {
89
90 StringBuffer buffer = new StringBuffer();
91 String str1 = "";
92 String str2 = "";
93 buffer.append("今天:");
94
95 // 取出有用的范圍
96 Pattern p = Pattern.compile("(.*)(<li class=\'dn on\' data-dn=\'7d1\'>)(.*?)(</li>)(.*)");
97 Matcher m = p.matcher(html);
98 if (m.matches()) {
99 str1 = m.group(3);
100 // 匹配日期,注:日期被包含在<h2> 和 </h2>中
101 p = Pattern.compile("(.*)(<h2>)(.*?)(</h2>)(.*)");
102 m = p.matcher(str1);
103 if(m.matches()){
104 str2 = m.group(3);
105 buffer.append(str2);
106 buffer.append("\n天氣:");
107 }
108 // 匹配天氣,注:天氣被包含在<p class="wea" title="..."> 和 </p>中
109 p = Pattern.compile("(.*)(<p class=\"wea\" title=)(.*?)(>)(.*?)(</p>)(.*)");
110 m = p.matcher(str1);
111 if(m.matches()){
112 str2 = m.group(5);
113 buffer.append(str2);
114 buffer.append("\n溫度:");
115 }
116 // 匹配溫度,注:溫度被包含在<p class=\"tem tem2\"> <span> 和 </span><i>中
117 p = Pattern.compile("(.*)(<p class=\"tem tem2\"> <span>)(.*?)(</span><i>)(.*)");
118 m = p.matcher(str1);
119 if(m.matches()){
120 str2 = m.group(3);
121 buffer.append(str2);
122 buffer.append("°~");
123 }
124 p = Pattern.compile("(.*)(<p class=\"tem tem1\"> <span>)(.*?)(</span><i>)(.*)");
125 m = p.matcher(str1);
126 if(m.matches()){
127 str2 = m.group(3);
128 buffer.append(str2);
129 buffer.append("°\n風力:");
130 }
131 // 匹配風,注:<i> 和 </i> 中
132 p = Pattern.compile("(.*)(<i>)(.*?)(</i>)(.*)");
133 m = p.matcher(str1);
134 if(m.matches()){
135 str2 = m.group(3);
136 buffer.append(str2);
137 }
138 }
139 return buffer.toString();
140 }
141
142 /**
143 * 對以上兩個方法進行封裝。
144 * @return
145 */
146 public static String getTodayTemperatureInfo() {
147 // 調用第一個方法,獲取html字符串
148 String html = httpRequest("http://www.weather.com.cn/html/weather/101280101.shtml");
149 // 調用第二個方法,過濾掉無用的信息
150 String result = htmlFiter(html);
151
152 return result;
153 }
154
155 /**
156 * 測試
157 * @param args
158 */
159 public static void main(String[] args) {
160 String info = getTodayTemperatureInfo();
161 System.out.println(info);
162 }
163 }
【詳解】
34-49行:通過url獲取網頁的源碼,沒什么好說的。
96行:在網頁上按F12,查看"今天"的html代碼,發現如下圖,所以我們第一步就是要過濾掉除這一段html代碼外的東西。
(.*)(<li class=\'dn on\' data-dn=\'7d1\'>)(.*?)(</li>)(.*) 這個正則表達式,很容易看出可以分為下面5組:
(.*) :匹配除換行符外任意東西0-N次
(<li class=\'dn on\' data-dn=\'7d1\'>) :匹配中間那段heml代碼一次
(.*?) : .*?為匹配的懶惰模式,意思是匹配除換行符外任意東西盡可能少次
(</li>) :匹配中間那段html代碼一次
(.*) :匹配除換行符外任意東西0-N次
這樣,我們就可用m.group(3)拿到匹配中間(.*?)的那一串代碼了。即我們需要的“今天”的天氣的代碼。

101行:中間那一段代碼拿出來后如下圖所示、還有很多無用的標簽。我們要想辦法繼續除去。方法同上。

106行:手動拼接上我們需要的字符串。
經過以上的處理,就完成了一個簡單的爬取啦。
中間正則表達式部分最不滿意,各路網友如果有好的建議麻煩留下寶貴的評論,感激不盡~

