您的位置:首页 > 编程语言 > Java开发

java通过url抓取网页数据-----正则表达式

2017-12-31 01:35 1151 查看
原文地址https://www.cnblogs.com/xiaoMzjm/p/3894805.html

【本文介绍】  

爬取别人网页上的内容,听上似乎很有趣的样子,只要几步,就可以获取到力所不能及的东西,例如呢?例如天气预报,总不能自己拿着仪器去测吧!当然,要获取天气预报还是用webService好。这里只是举个例子。话不多说了,上看看效果吧。

【效果】

我们随便找个天气预报的网站来试试:http://www.weather.com.cn/html/weather/101280101.shtml

从图中可用看出,今天(6日)的天气。我们就以这个为例,获取今天的天气吧!

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行:手动拼接上我们需要的字符串。

经过以上的处理,就完成了一个简单的爬取啦。

中间正则表达式部分最不满意,各路网友如果有好的建议麻烦留下宝贵的评论,感激不尽~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: