您的位置:首页 > Web前端 > HTML

Jericho Html Parser初探

2015-10-16 14:50 477 查看


Jericho Html Parser初探

作者:SharpStill

Jericho作为其SourceForge上人气最高的最新Html解析框架,自然有其强大的理由。但是由于目前中国人使用的不多,因此网上的中文教程和资料不多,所以造成了大家的学习困难。因此,我们从学习复杂度,代码量等初学者入门指标来看看这个框架的魔力吧。可以使用制作开源爬虫引擎。

 

这个例子我们以淘宝这样的购物网站作为解析实例。

淘宝网的页面分为http://list.taobao.com http://www.taobao.com/go/chn/game,(类似album)和http://item.taobao.com(类似video)和面还有许许多多这样的页面,我们利用Jericho
Html Parser作为页面解析框架,来看一下他的威力。

这个网页解析框架的xml书写如下:

JerichoHtml Parser的核心的类便是Source类,source类代表了html文档,他可以从URL得到文档或者从String得到。

In certain circumstances you may be able to improve performance bycalling the
fullSequentialParse()
method
before calling anytagsearch methods. See the documentation of the
fullSequentialParse()
method
for details.

在其说明文档中有这样一句话,就是说如果在特定情况下可以使用
fullSequentialParse()
方法,提高解析速度,这个方法里的说明:Calling
this method can greatly improve performance if most or allof the tags in the document need to be parsed.

如果在一个类里将大部分或者所有的tag标记都解析了的话,比如我们经常需要提取出网页所有的URL或者图片链接,在这种情况下使用这种方法可以加快提取速度,但是值得注意的一点是:只有在Source对象被new出来的后面一句紧接着调用这句话有效。紧接着调用Tag
Search Method(文档中有详细说明)即可。

我们以提取这个页面为例:



这个页面包含以下几点:价格,运费信息,所在地区,收藏人气,宝贝类型。利用这个页面提取,看看其编程效率能提高多少。

package com.test.html;

import java.util.List;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.Source;

import com.test.html.bean.ShoppingDetail;

public class HtmlParseTest {

public static ShoppingDetail extract(String inputHtml){
Source source = new Source(inputHtml);
Element form = source.getElementById("J_FrmBid");
List<Element> inputArea = form.getAllElements("input");
String price ="";
String area ="";
String transportInfo="";

for(Element input : inputArea){
if(input.getAttributeValue("name").equals("buy_now"))price = input.getAttributeValue("value");
if(input.getAttributeValue("name").equals("region"))area = input.getAttributeValue("value");
if(input.getAttributeValue("name").equals("who_pay_ship"))transportInfo = input.getAttributeValue("value");

}
Element others = source.getAllElementsByClass("other clearfix").get(0);
String otherInfo = others.getContent().getTextExtractor().toString().trim();
int startBabyType =otherInfo.indexOf("宝贝类型:");
int endBabyType= otherInfo.indexOf("收藏人气:");
String babyType = otherInfo.substring(startBabyType+5,endBabyType);
int endStore = otherInfo.indexOf("类似收藏");
String storeCount = otherInfo.substring(endBabyType+5,endStore-1).trim();
ShoppingDetail detail = new ShoppingDetail();
detail.setArea(area);
detail.setBabyType(babyType);
detail.setPrice(price);
detail.setStroreCount(Integer.parseInt(storeCount));
detail.setTransportInfo(transportInfo);
return detail;
}

public static void main(String[] args) throws Exception {
String content = HttpClientUtils.getContent("http://item.taobao.com/item.htm?id=3144581940", "UTF-8");
ShoppingDetail detail = HtmlParseTest.extract(content);
System.out.println(detail);


运行结果如下所示

com.test.html.bean.ShoppingDetail@1aaa14a[title=索尼
PSP 4.3寸摇杆游戏机 8G mp5高清电影+TV输出+收音,price=235.00,transportInfo=卖家承担运费,area=广东深圳,stroreCount=17711,babyType=全新
]

 

提取这个页面的核心代码仅为上面的那个函数,可以说从编程的复杂度而言比HtmlParser减少了不少,而且也没有繁琐的访问者模式了。

下面作为对比,我们来看看HtmlParser在这个页面解析上所做的代码量:

@Override
public boolean execute(Context context) throws Exception {
//spring若与commons chain可以集成IOC的话,就删去
parserTool = new SingleHtmlParserTool();
filterUtils = new FilterUtils();
filterUtils.setTool(new PropertiesTool("/Config/Properties/TaobaoFilter.properties"));

//这一段若研究了spring的胶水机制就删了

String url = ((String)context.get("url")).toLowerCase();

String seller_Url = "";
String seller_Nickname = "";
String seller_Taobao_Id = "";

if(url.contains(Url_Pattern)){
System.out.println("开始提取数据自"+url);
NodeList forms = parserTool.getContainerInnerTags(url, formFilter);
Map<String,String> valueMap = new HashMap<String,String>();//key-value map to store
for(int i = 0;i<forms.size();i++){
FormTag form = (FormTag)forms.elementAt(i);
NodeList inputs = form.getFormInputs();
for(int j = 0;j<inputs.size();j++){
InputTag input = (InputTag)inputs.elementAt(j);
String inputName = input.getAttribute("name");
String inputValue = input.getAttribute("value");
valueMap.put(inputName, inputValue);
}

//进入卖家分析程序分析时要用的一些Context中的值
seller_Taobao_Id = valueMap.get("seller_id");
seller_Nickname = valueMap.get("seller_nickname");
seller_Url = "http://rate.taobao.com/user-rate-"+seller_Taobao_Id+".htm";
//进入卖家分析程序分析时要用的一些Context中的值

filterUtils.filterMap(valueMap, filterStoreItemKey,
merchandiseItemSeparatorKey,
DictItem.MerchandiseItemSiteToEngine);// 过滤网址上的其他杂质<inputname="杂质" />,保证最后存于数据库的map被返回
valueMap.put("TaobaoSite_Url", url);// 最后把网页"内容"里提取不出来的url加入其中

// 存入数据库
IBasicSqlDao dao = BeanMapDaoUsingCommonsBeanutils.getInstance();
dao.storeMapToDb(valueMap, sqlId, MerchandiseItem.class);
// 存入数据库
for(Map.Entry<String, String> entry : valueMap.entrySet()){
System.out.println(entry.getKey()+":"+entry.getValue());
}
System.out.println("---页面"+url+"提取完毕---");
//重构可以删去
valueMap.clear();// 清除map
}
Context sellerContext = new UrlContext(seller_Url);
sellerContext.put("Seller_Nickname", seller_Nickname);
sellerContext.put("Seller_Taobao_Id", seller_Taobao_Id);
EmergencyLinkUrl.addUnVisitUrl(sellerContext, this);

return true;
}
return false;
}


可以明显看到,Jercho从编程风格来看,拥有这几大优势:

去除了内部类,由于Html Parser使用过滤器或访问者模式,不可避免地引入内部类。

编程使用泛型,简化编写,Html Parser没有使用泛型作为其框架,可能其创造年代较早,但是大量使用了设计模式,可以窥见其作者对设计模式的功力很深。

可以直接提取页面文本信息,将HTML标签去除。这个在全文搜索时非常常用。

Tag Search Method类似XPath的提取方式,可以不受限制地提取若干层以下的元素Element。

目前观察到的几大优势使我们有理由相信,Jercho在未来的Html解析届会成为翘楚的。以下为一篇不错的Jercho Html Parser文章推荐下:

http://www.ehelper.com.cn/blog/post/httpclient-jericho.html

 

 

我又查了一下资料,发现 jsoup HTML解析器比 htmpparser 更好

HtmlUnit 比 httpclient更易用

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息