网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。——百度百科
爬虫最基础的操作其实就是分析静态网页,从而获取有价值的信息。现在的网页一般均为Html格式的,当然http请求也会返回xml,json等数据格式。在入门篇我们以html为例。
分析需求
我打算在链家网上爬取北京一个小区的房价信息,每天爬一次,如果有房价信息更新,或者有新房,则在log文件里面打一条log。
步骤
获取小区网页html->分析网页元素->获取有用的信息->比对已经存在的房价信息->打log
获取网页
这里我们用java自带的httpclient发送http请求并用字符串存取。
public String httpGet(String url)
{
String result = "";
BufferedReader in = null;
try {
URL realUrl = new URL(url);
System.out.println(realUrl + "\n" + url);
urlConnection = realUrl.openConnection();
urlConnection.connect();
in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
System.out.println(urlConnection.getHeaderFields());
String line;
while((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e){
System.out.println("发送get请求异常!" + e);
e.printStackTrace();
} finally {
try{
if(in != null){
in.close();
}
}catch (Exception e2){
e2.printStackTrace();
}
}
return result;
}
分析网页元素
打开网页检查元素即可,一般浏览器都会自带匹配,慢慢往下寻找,可以找到houselist,如下图。所以我需要的信息就全部在这个里面了。
查看一下每一条item的信息,并找出自己关心的几个元素,title,price等。
获取有用的信息
然后我们要做的就是从http请求返回的字符串中找到相应的信息。用正则表达式匹配是一种不错的选择。其中()所包括的表示一个我们所关心的元素,最后正则表达式如下所示。
// 房产数据匹配正则
public static final String houseInfoExpression = "data-index=\"(.+?)\".+?" +//标签
"data-id=\"(.+?)\">.*?" +//数据id
"<h2><a.+?title=.+?>(.+?)[ ]{0,}</a>.*?" +//title
"region.+?>(.+?)[ ]{0,}<.*?" +//小区
"meters.+?>(.+?)[ ]{0,}<.*?" +//大小
"price.+?num.+?>(.+?)</span>.*?" +//价格
"price-pre.+?>(.+?)</div>";//每平米价格
下面要做的就是去匹配数据了。java中主要用Pattern和Matcher去做正则匹配
//获取当前页的房产信息
ArrayList<HouseInfo> results = new ArrayList<HouseInfo>();
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(targetStr);
boolean isFind = matcher.find();
while(isFind){//如果匹配到记录相应的信息。
HouseInfo houseInfo = new HouseInfo();
houseInfo.setHouseIndex(Integer.parseInt(matcher.group(1)));
houseInfo.setHouseDataId(matcher.group(2));
houseInfo.setHouseTitle(matcher.group(3));
houseInfo.setHouseRegion(matcher.group(4));
houseInfo.setHouseArea(matcher.group(5));
houseInfo.setHousePrice(Integer.parseInt(matcher.group(6)));
houseInfo.setHousePricePer(matcher.group(7));
JSONObject jsonObject = new JSONObject(houseInfo);
System.out.println(jsonObject);
}