【本文介绍】  

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

【效果】

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

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

最终后台打印出:

今天:6日
天气:雷阵雨
温度:26°~34°
风力:微风

【思路】

1、通过url获取输入流————2、获取网页html代码————3、用正则表达式抽取有用的信息————4、拼装成想要的格式

其实最难的一点事第3点,如果正则表示式不熟,基本上在这一步就会挂掉了——例如我T_T。下面为了抽取到正确的数据,我匹配了多次,如果能一次匹配的话,那代码量就少多了!

【代码】

 package com.zjm.www.test;

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern; /**
* 描述:趴取网页上的今天的天气
* @author zjm
* @time 2014/8/6
*/
public class TodayTemperatureService { /**
* 发起http get请求获取网页源代码
* @param requestUrl String 请求地址
* @return String 该地址返回的html字符串
*/
private static String httpRequest(String requestUrl) { StringBuffer buffer = null;
BufferedReader bufferedReader = null;
InputStreamReader inputStreamReader = null;
InputStream inputStream = null;
HttpURLConnection httpUrlConn = null; try {
// 建立get请求
URL url = new URL(requestUrl);
httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoInput(true);
httpUrlConn.setRequestMethod("GET"); // 获取输入流
inputStream = httpUrlConn.getInputStream();
inputStreamReader = new InputStreamReader(inputStream, "utf-8");
bufferedReader = new BufferedReader(inputStreamReader); // 从输入流读取结果
buffer = new StringBuffer();
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
} } catch (Exception e) {
e.printStackTrace();
} finally {
// 释放资源
if(bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inputStreamReader != null){
try {
inputStreamReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(httpUrlConn != null){
httpUrlConn.disconnect();
}
}
return buffer.toString();
} /**
* 过滤掉html字符串中无用的信息
* @param html String html字符串
* @return String 有用的数据
*/
private static String htmlFiter(String html) { StringBuffer buffer = new StringBuffer();
String str1 = "";
String str2 = "";
buffer.append("今天:"); // 取出有用的范围
Pattern p = Pattern.compile("(.*)(<li class=\'dn on\' data-dn=\'7d1\'>)(.*?)(</li>)(.*)");
Matcher m = p.matcher(html);
if (m.matches()) {
str1 = m.group(3);
// 匹配日期,注:日期被包含在<h2> 和 </h2>中
p = Pattern.compile("(.*)(<h2>)(.*?)(</h2>)(.*)");
m = p.matcher(str1);
if(m.matches()){
str2 = m.group(3);
buffer.append(str2);
buffer.append("\n天气:");
}
// 匹配天气,注:天气被包含在<p class="wea" title="..."> 和 </p>中
p = Pattern.compile("(.*)(<p class=\"wea\" title=)(.*?)(>)(.*?)(</p>)(.*)");
m = p.matcher(str1);
if(m.matches()){
str2 = m.group(5);
buffer.append(str2);
buffer.append("\n温度:");
}
// 匹配温度,注:温度被包含在<p class=\"tem tem2\"> <span> 和 </span><i>中
p = Pattern.compile("(.*)(<p class=\"tem tem2\"> <span>)(.*?)(</span><i>)(.*)");
m = p.matcher(str1);
if(m.matches()){
str2 = m.group(3);
buffer.append(str2);
buffer.append("°~");
}
p = Pattern.compile("(.*)(<p class=\"tem tem1\"> <span>)(.*?)(</span><i>)(.*)");
m = p.matcher(str1);
if(m.matches()){
str2 = m.group(3);
buffer.append(str2);
buffer.append("°\n风力:");
}
// 匹配风,注:<i> 和 </i> 中
p = Pattern.compile("(.*)(<i>)(.*?)(</i>)(.*)");
m = p.matcher(str1);
if(m.matches()){
str2 = m.group(3);
buffer.append(str2);
}
}
return buffer.toString();
} /**
* 对以上两个方法进行封装。
* @return
*/
public static String getTodayTemperatureInfo() {
// 调用第一个方法,获取html字符串
String html = httpRequest("http://www.weather.com.cn/html/weather/101280101.shtml");
// 调用第二个方法,过滤掉无用的信息
String result = htmlFiter(html); return result;
} /**
* 测试
* @param args
*/
public static void main(String[] args) {
String info = getTodayTemperatureInfo();
System.out.println(info);
}
}

【详解】

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

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

中间正则表达式部分最不满意,各路网友如果有好的建议麻烦留下宝贵的评论,感激不尽~

最新文章

  1. 【leetcode】Merge Intervals
  2. .NET方向高级开发人员面试时应该事先考虑的问题
  3. (转)对各种初始化函数的理解:OnInitDialog、InitInstance、InitApplication函数的理解
  4. Oracle中建表空间以及用户
  5. 【poj1006-biorhythms】中国剩余定理
  6. FineUI页面布局
  7. 卸载XCode插件的方法
  8. 关于狄克斯特拉算法(dijkstra)总结
  9. Android水印相机
  10. centos yum install nginx
  11. Selenium(基于JAVA语言)-》在eclipse上运行web项目在Mac系统上启动时提示nodename nor servname provided解决办法
  12. asp.net mvc Htmlhelper简单扩展
  13. Matlab面向对象编程基础
  14. BZOJ 1089 SCOI2003 严格n元树 动态规划+高精度
  15. LeetCode——Generate Parentheses
  16. maven添加本地jar
  17. FIR滤波器实例
  18. Web App三年将取代原生App?
  19. Swift中UIView类方法(animateWithDuration)的使用
  20. do_gettimeofday使用方法

热门文章

  1. repcached与mysql缓存測试
  2. 大数据(13) - Spark的安装部署与简单使用
  3. contract
  4. 静态内部类定义在类中,任何方法外,用static定义
  5. 【NOIP模拟题】Graph(tarjan+dfs)
  6. strust2自定义interceptor的基本方法及操作
  7. Linux下Vi/Vim的使用方法
  8. php7 宏杂记
  9. freemarker0
  10. stringstream类操作字符串流