原文地址/xiaoMzjm/p/3894805.html
【本文介绍】
爬取别人网页上的内容,听上似乎很有趣的样子,只要几步,就可以获取到力所不能及的东西,例如呢?例如天气预报,总不能自己拿着仪器去测吧!当然,要获取天气预报还是用webService好。这里只是举个例子。话不多说了,上看看效果吧。
【效果】
我们随便找个天气预报的网站来试试:/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 .HttpURLConnection;8 import .URL;9 import java.util.regex.Matcher;10 import java.util.regex.Pattern;11 12 /**13 * 描述:趴取网页上的今天的天气14 * @authorzjm 15 * @time/8/616 */17 public class TodayTemperatureService {1819/** 20* 发起http get请求获取网页源代码 21* @param requestUrlString 请求地址22* @return String 该地址返回的html字符串23*/ 24private 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*/ 88private 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 = pile("(.*)(<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 = pile("(.*)(<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 = pile("(.*)(<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 = pile("(.*)(<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 = pile("(.*)(<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 = pile("(.*)(<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}141142/** 143* 对以上两个方法进行封装。144* @return 145*/ 146public static String getTodayTemperatureInfo() { 147 // 调用第一个方法,获取html字符串148 String html = httpRequest("/html/weather/101280101.shtml"); 149 // 调用第二个方法,过滤掉无用的信息150 String result = htmlFiter(html); 151 152 return result; 153} 154 155/**156* 测试157* @param args158*/159public 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行:手动拼接上我们需要的字符串。
经过以上的处理,就完成了一个简单的爬取啦。
中间正则表达式部分最不满意,各路网友如果有好的建议麻烦留下宝贵的评论,感激不尽~