谈谈html页面的解析(一)

如今,互联网上的信息越来越多,互联网的信息已经成为一个越来越大的矿山,这个里面有黄金也有垃圾,我们坐在这个矿山上,如何挖掘其中的金子,已经越来越受到重视,而这个挖掘过程的第一步就是需要将这些非结构化的数据转变为结构化的数据。最简单的搜索的爬虫需要这种转变,由WEB到WAP的转码需要这种转变,WEB数据的应用也需要这种转变。

我们通过浏览器所看到的页面信息,是由包含了很多的页面元素组装在一起的,其中有“干货”的图片和文字,也有我们意识不到的布局结构(div、tr、td等),所有的这些页面元素组织成了我们能够看到的Page页面。但是机器能看到的是什么呢?一堆html代码,当我们使用浏览器中的“查看源代码”看到的html代码就是机器读到的html代码,然后浏览器在按照一些列的标准将这些元素进行呈现,而我们需要做的就是将我们需要信息从这些html文本中抽取出来.

html代码是xml的一种特殊情况,因此可以使用解析XML的方式来解析html代码,解析xml代码最好的方式莫属使用xpath了,使用xpath比较理想的方式,这个比较理想是因为使用Firebug或一些浏览器插件可以直接定位到你想要的元素的Xpath,这样就减少了定位到你要获取到的元素的时间。使用Firebug定位xpath的方法是:在需要解析的页面中按F12,调出Firebug,然后选中需要解析的元素节点,右键点击鼠标,在弹出的菜单中选择“复制Xpath”就可以复制出该节点的Xpath了。另外在解析xml方面,建议使用dom4j,做过对比,这种方式应该算是一种比较快的方式(关于这个问题会单独写一篇测评的博文)。以下是使用dom4j获取到节点信息的示例代码:
SAXReader saxReader = new SAXReader();
ByteArrayInputStream input = new ByteArrayInputStream(content.getBytes("utf-8"));
Document document = saxReader.read(input);//构建document
List list = document.selectNodes(xpath);//使用xpath来获取符合条件的节点

对于熟悉CSS或jQuery的同学使用这种也可以选择Jsoup(http://jsoup.org/)这一开源的组件,这个开园组件可以使用jquery-like的语法来选择节点,这些可以参见jsoup的api说明http://jsoup.org/apidocs/org/jsoup/select/Selector.html。这种方法特别适合于页面结构比较复杂,但是大多数你需要获取的元素都存在id属性或者class属性,不过使用jsoup的时候一般都搭配apache的http-client,而不是使用jsoup自带的下载方式,原因是jsoup自带的下载方法存在bug,会导致下载页面失败造成假死。这个也会再开一篇文章描述。以下是使用jsoup的示例:

HttpClient client = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url.trim());
HttpResponse response = client.execute(httpget);
String charset = "";
String contentType = response.getEntity().getContentType().getValue();
if(StringUtils.isNotEmpty(contentType)&&contentType.indexOf("charset")>0){
     charset = contentType.substring(contentType.indexOf("charset=")+"charset=".length());
}
if(StringUtils.isEmpty(charset)){
     charset = "UTF-8";
}
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), charset));
String line;
while ((line = br.readLine()) != null) {
     sb.append(line);
}
String content = sb.toString();
Document document = Jsoup.parse(content);
Elements ele = document.select(selector);

到现在为止,貌似我们的问题都解决了,但是实际上这才走了第一步,因为解析页面还面临着以下两个问题:

1、有些页面内容时JS渲染的,比如说图书的价格,比如说视频的播放次数;

2、有些信息我们在一个页面中抓不全,我们可能需要通过这个页面的一个链接到另外一个页面中获取其他信息,比如我们从视频的播放页面中能获取到视频的名称,然后通过“详情”链接到详细页面中获取主演、导演等其他信息。

3、有的时候我们解析的不是标签中的文本信息,而是标签中某些属性,比如图片我们需要的是src属性,超链接我们需要的href属性。

4、有的时候我们需要的不是简单的文本,而是里面的数字或者时间。

关于这些问题,将在第二篇中说明。

互联网从业者一枚,欢迎微博互粉,切磋学习:http://weibo.com/icemanhit

相关推荐